Merge "Fix ActivityEmbedding placeholder launching above fullscreen activity" into tm-qpr-dev am: 4706a5c650
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20647614 Change-Id: I8e51bd63e2b25065d0f98eaa1ae176cd99858be7 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
|||||||
import static android.app.WindowConfiguration.WindowingMode;
|
import static android.app.WindowConfiguration.WindowingMode;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.annotation.TestApi;
|
import android.annotation.TestApi;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -57,14 +58,33 @@ public final class TaskFragmentCreationParams implements Parcelable {
|
|||||||
|
|
||||||
/** The initial windowing mode of the TaskFragment. Inherits from parent if not set. */
|
/** The initial windowing mode of the TaskFragment. Inherits from parent if not set. */
|
||||||
@WindowingMode
|
@WindowingMode
|
||||||
private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
|
private final int mWindowingMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fragment token of the paired primary TaskFragment.
|
||||||
|
* When it is set, the new TaskFragment will be positioned right above the paired TaskFragment.
|
||||||
|
* Otherwise, the new TaskFragment will be positioned on the top of the Task by default.
|
||||||
|
*
|
||||||
|
* This is different from {@link WindowContainerTransaction#setAdjacentTaskFragments} as we may
|
||||||
|
* set this when the pair of TaskFragments are stacked, while adjacent is only set on the pair
|
||||||
|
* of TaskFragments that are in split.
|
||||||
|
*
|
||||||
|
* This is needed in case we need to launch a placeholder Activity to split below a transparent
|
||||||
|
* always-expand Activity.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private final IBinder mPairedPrimaryFragmentToken;
|
||||||
|
|
||||||
private TaskFragmentCreationParams(
|
private TaskFragmentCreationParams(
|
||||||
@NonNull TaskFragmentOrganizerToken organizer,
|
@NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken,
|
||||||
@NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
|
@NonNull IBinder ownerToken, @NonNull Rect initialBounds,
|
||||||
|
@WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken) {
|
||||||
mOrganizer = organizer;
|
mOrganizer = organizer;
|
||||||
mFragmentToken = fragmentToken;
|
mFragmentToken = fragmentToken;
|
||||||
mOwnerToken = ownerToken;
|
mOwnerToken = ownerToken;
|
||||||
|
mInitialBounds.set(initialBounds);
|
||||||
|
mWindowingMode = windowingMode;
|
||||||
|
mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -92,12 +112,22 @@ public final class TaskFragmentCreationParams implements Parcelable {
|
|||||||
return mWindowingMode;
|
return mWindowingMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO(b/232476698): remove the hide with adding CTS for this in next release.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public IBinder getPairedPrimaryFragmentToken() {
|
||||||
|
return mPairedPrimaryFragmentToken;
|
||||||
|
}
|
||||||
|
|
||||||
private TaskFragmentCreationParams(Parcel in) {
|
private TaskFragmentCreationParams(Parcel in) {
|
||||||
mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
|
mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
|
||||||
mFragmentToken = in.readStrongBinder();
|
mFragmentToken = in.readStrongBinder();
|
||||||
mOwnerToken = in.readStrongBinder();
|
mOwnerToken = in.readStrongBinder();
|
||||||
mInitialBounds.readFromParcel(in);
|
mInitialBounds.readFromParcel(in);
|
||||||
mWindowingMode = in.readInt();
|
mWindowingMode = in.readInt();
|
||||||
|
mPairedPrimaryFragmentToken = in.readStrongBinder();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -108,6 +138,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
|
|||||||
dest.writeStrongBinder(mOwnerToken);
|
dest.writeStrongBinder(mOwnerToken);
|
||||||
mInitialBounds.writeToParcel(dest, flags);
|
mInitialBounds.writeToParcel(dest, flags);
|
||||||
dest.writeInt(mWindowingMode);
|
dest.writeInt(mWindowingMode);
|
||||||
|
dest.writeStrongBinder(mPairedPrimaryFragmentToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -132,6 +163,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
|
|||||||
+ " ownerToken=" + mOwnerToken
|
+ " ownerToken=" + mOwnerToken
|
||||||
+ " initialBounds=" + mInitialBounds
|
+ " initialBounds=" + mInitialBounds
|
||||||
+ " windowingMode=" + mWindowingMode
|
+ " windowingMode=" + mWindowingMode
|
||||||
|
+ " pairedFragmentToken=" + mPairedPrimaryFragmentToken
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +191,9 @@ public final class TaskFragmentCreationParams implements Parcelable {
|
|||||||
@WindowingMode
|
@WindowingMode
|
||||||
private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
|
private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private IBinder mPairedPrimaryFragmentToken;
|
||||||
|
|
||||||
public Builder(@NonNull TaskFragmentOrganizerToken organizer,
|
public Builder(@NonNull TaskFragmentOrganizerToken organizer,
|
||||||
@NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
|
@NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
|
||||||
mOrganizer = organizer;
|
mOrganizer = organizer;
|
||||||
@@ -180,14 +215,29 @@ public final class TaskFragmentCreationParams implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the fragment token of the paired primary TaskFragment.
|
||||||
|
* When it is set, the new TaskFragment will be positioned right above the paired
|
||||||
|
* TaskFragment. Otherwise, the new TaskFragment will be positioned on the top of the Task
|
||||||
|
* by default.
|
||||||
|
*
|
||||||
|
* This is needed in case we need to launch a placeholder Activity to split below a
|
||||||
|
* transparent always-expand Activity.
|
||||||
|
*
|
||||||
|
* TODO(b/232476698): remove the hide with adding CTS for this in next release.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Builder setPairedPrimaryFragmentToken(@Nullable IBinder fragmentToken) {
|
||||||
|
mPairedPrimaryFragmentToken = fragmentToken;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Constructs the options to create TaskFragment with. */
|
/** Constructs the options to create TaskFragment with. */
|
||||||
@NonNull
|
@NonNull
|
||||||
public TaskFragmentCreationParams build() {
|
public TaskFragmentCreationParams build() {
|
||||||
final TaskFragmentCreationParams result = new TaskFragmentCreationParams(
|
return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken,
|
||||||
mOrganizer, mFragmentToken, mOwnerToken);
|
mInitialBounds, mWindowingMode, mPairedPrimaryFragmentToken);
|
||||||
result.mInitialBounds.set(mInitialBounds);
|
|
||||||
result.mWindowingMode = mWindowingMode;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,8 +133,18 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a TaskFragment for the secondary activity.
|
// Create a TaskFragment for the secondary activity.
|
||||||
createTaskFragmentAndStartActivity(wct, secondaryFragmentToken, ownerToken,
|
final TaskFragmentCreationParams fragmentOptions = new TaskFragmentCreationParams.Builder(
|
||||||
secondaryFragmentBounds, windowingMode, activityIntent,
|
getOrganizerToken(), secondaryFragmentToken, ownerToken)
|
||||||
|
.setInitialBounds(secondaryFragmentBounds)
|
||||||
|
.setWindowingMode(windowingMode)
|
||||||
|
// Make sure to set the paired fragment token so that the new TaskFragment will be
|
||||||
|
// positioned right above the paired TaskFragment.
|
||||||
|
// This is needed in case we need to launch a placeholder Activity to split below a
|
||||||
|
// transparent always-expand Activity.
|
||||||
|
.setPairedPrimaryFragmentToken(launchingFragmentToken)
|
||||||
|
.build();
|
||||||
|
createTaskFragment(wct, fragmentOptions);
|
||||||
|
wct.startActivityInTaskFragment(secondaryFragmentToken, ownerToken, activityIntent,
|
||||||
activityOptions);
|
activityOptions);
|
||||||
|
|
||||||
// Set adjacent to each other so that the containers below will be invisible.
|
// Set adjacent to each other so that the containers below will be invisible.
|
||||||
@@ -173,8 +183,21 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
|||||||
*/
|
*/
|
||||||
void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
|
void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
|
||||||
@NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
|
@NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
|
||||||
final TaskFragmentCreationParams fragmentOptions =
|
final TaskFragmentCreationParams fragmentOptions = new TaskFragmentCreationParams.Builder(
|
||||||
createFragmentOptions(fragmentToken, ownerToken, bounds, windowingMode);
|
getOrganizerToken(), fragmentToken, ownerToken)
|
||||||
|
.setInitialBounds(bounds)
|
||||||
|
.setWindowingMode(windowingMode)
|
||||||
|
.build();
|
||||||
|
createTaskFragment(wct, fragmentOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createTaskFragment(@NonNull WindowContainerTransaction wct,
|
||||||
|
@NonNull TaskFragmentCreationParams fragmentOptions) {
|
||||||
|
if (mFragmentInfos.containsKey(fragmentOptions.getFragmentToken())) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"There is an existing TaskFragment with fragmentToken="
|
||||||
|
+ fragmentOptions.getFragmentToken());
|
||||||
|
}
|
||||||
wct.createTaskFragment(fragmentOptions);
|
wct.createTaskFragment(fragmentOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,18 +212,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
|||||||
wct.reparentActivityToTaskFragment(fragmentToken, activity.getActivityToken());
|
wct.reparentActivityToTaskFragment(fragmentToken, activity.getActivityToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ownerToken The token of the activity that creates this task fragment. It does not
|
|
||||||
* have to be a child of this task fragment, but must belong to the same task.
|
|
||||||
*/
|
|
||||||
private void createTaskFragmentAndStartActivity(@NonNull WindowContainerTransaction wct,
|
|
||||||
@NonNull IBinder fragmentToken, @NonNull IBinder ownerToken, @NonNull Rect bounds,
|
|
||||||
@WindowingMode int windowingMode, @NonNull Intent activityIntent,
|
|
||||||
@Nullable Bundle activityOptions) {
|
|
||||||
createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
|
|
||||||
wct.startActivityInTaskFragment(fragmentToken, ownerToken, activityIntent, activityOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
|
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
|
||||||
@NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
|
@NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
|
||||||
WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
|
WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
|
||||||
@@ -238,22 +249,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
|||||||
wct.setCompanionTaskFragment(secondary, finishSecondaryWithPrimary ? primary : null);
|
wct.setCompanionTaskFragment(secondary, finishSecondaryWithPrimary ? primary : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskFragmentCreationParams createFragmentOptions(@NonNull IBinder fragmentToken,
|
|
||||||
@NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
|
|
||||||
if (mFragmentInfos.containsKey(fragmentToken)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"There is an existing TaskFragment with fragmentToken=" + fragmentToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TaskFragmentCreationParams.Builder(
|
|
||||||
getOrganizerToken(),
|
|
||||||
fragmentToken,
|
|
||||||
ownerToken)
|
|
||||||
.setInitialBounds(bounds)
|
|
||||||
.setWindowingMode(windowingMode)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
|
void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
|
||||||
@Nullable Rect bounds) {
|
@Nullable Rect bounds) {
|
||||||
if (!mFragmentInfos.containsKey(fragmentToken)) {
|
if (!mFragmentInfos.containsKey(fragmentToken)) {
|
||||||
|
|||||||
@@ -1218,14 +1218,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity,
|
TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity,
|
||||||
@NonNull Activity activityInTask, int taskId) {
|
@NonNull Activity activityInTask, int taskId) {
|
||||||
return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */,
|
return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */,
|
||||||
activityInTask, taskId);
|
activityInTask, taskId, null /* pairedPrimaryContainer */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
|
TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
|
||||||
@NonNull Activity activityInTask, int taskId) {
|
@NonNull Activity activityInTask, int taskId) {
|
||||||
return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
|
return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
|
||||||
activityInTask, taskId);
|
activityInTask, taskId, null /* pairedPrimaryContainer */);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1237,10 +1237,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
* @param activityInTask activity in the same Task so that we can get the Task bounds
|
* @param activityInTask activity in the same Task so that we can get the Task bounds
|
||||||
* if needed.
|
* if needed.
|
||||||
* @param taskId parent Task of the new TaskFragment.
|
* @param taskId parent Task of the new TaskFragment.
|
||||||
|
* @param pairedPrimaryContainer the paired primary {@link TaskFragmentContainer}. When it is
|
||||||
|
* set, the new container will be added right above it.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
TaskFragmentContainer newContainer(@Nullable Activity pendingAppearedActivity,
|
TaskFragmentContainer newContainer(@Nullable Activity pendingAppearedActivity,
|
||||||
@Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId) {
|
@Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId,
|
||||||
|
@Nullable TaskFragmentContainer pairedPrimaryContainer) {
|
||||||
if (activityInTask == null) {
|
if (activityInTask == null) {
|
||||||
throw new IllegalArgumentException("activityInTask must not be null,");
|
throw new IllegalArgumentException("activityInTask must not be null,");
|
||||||
}
|
}
|
||||||
@@ -1249,7 +1252,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
}
|
}
|
||||||
final TaskContainer taskContainer = mTaskContainers.get(taskId);
|
final TaskContainer taskContainer = mTaskContainers.get(taskId);
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
|
final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
|
||||||
pendingAppearedIntent, taskContainer, this);
|
pendingAppearedIntent, taskContainer, this, pairedPrimaryContainer);
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import android.util.Size;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowMetrics;
|
import android.view.WindowMetrics;
|
||||||
|
import android.window.TaskFragmentCreationParams;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
import androidx.annotation.GuardedBy;
|
import androidx.annotation.GuardedBy;
|
||||||
@@ -307,10 +308,13 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int taskId = primaryContainer.getTaskId();
|
final int taskId = primaryContainer.getTaskId();
|
||||||
final TaskFragmentContainer secondaryContainer = mController.newContainer(activityIntent,
|
final TaskFragmentContainer secondaryContainer = mController.newContainer(
|
||||||
launchingActivity, taskId);
|
null /* pendingAppearedActivity */, activityIntent, launchingActivity, taskId,
|
||||||
final int windowingMode = mController.getTaskContainer(taskId)
|
// Pass in the primary container to make sure it is added right above the primary.
|
||||||
.getWindowingModeForSplitTaskFragment(primaryRectBounds);
|
primaryContainer);
|
||||||
|
final TaskContainer taskContainer = mController.getTaskContainer(taskId);
|
||||||
|
final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
|
||||||
|
primaryRectBounds);
|
||||||
mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
|
mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
|
||||||
rule, splitAttributes);
|
rule, splitAttributes);
|
||||||
startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
|
startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
|
||||||
@@ -412,17 +416,18 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
|
void createTaskFragment(@NonNull WindowContainerTransaction wct,
|
||||||
@NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
|
@NonNull TaskFragmentCreationParams fragmentOptions) {
|
||||||
final TaskFragmentContainer container = mController.getContainer(fragmentToken);
|
final TaskFragmentContainer container = mController.getContainer(
|
||||||
|
fragmentOptions.getFragmentToken());
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Creating a task fragment that is not registered with controller.");
|
"Creating a task fragment that is not registered with controller.");
|
||||||
}
|
}
|
||||||
|
|
||||||
container.setLastRequestedBounds(bounds);
|
container.setLastRequestedBounds(fragmentOptions.getInitialBounds());
|
||||||
container.setLastRequestedWindowingMode(windowingMode);
|
container.setLastRequestedWindowingMode(fragmentOptions.getWindowingMode());
|
||||||
super.createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
|
super.createTaskFragment(wct, fragmentOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -118,10 +118,12 @@ class TaskFragmentContainer {
|
|||||||
/**
|
/**
|
||||||
* Creates a container with an existing activity that will be re-parented to it in a window
|
* Creates a container with an existing activity that will be re-parented to it in a window
|
||||||
* container transaction.
|
* container transaction.
|
||||||
|
* @param pairedPrimaryContainer when it is set, the new container will be add right above it
|
||||||
*/
|
*/
|
||||||
TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
|
TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
|
||||||
@Nullable Intent pendingAppearedIntent, @NonNull TaskContainer taskContainer,
|
@Nullable Intent pendingAppearedIntent, @NonNull TaskContainer taskContainer,
|
||||||
@NonNull SplitController controller) {
|
@NonNull SplitController controller,
|
||||||
|
@Nullable TaskFragmentContainer pairedPrimaryContainer) {
|
||||||
if ((pendingAppearedActivity == null && pendingAppearedIntent == null)
|
if ((pendingAppearedActivity == null && pendingAppearedIntent == null)
|
||||||
|| (pendingAppearedActivity != null && pendingAppearedIntent != null)) {
|
|| (pendingAppearedActivity != null && pendingAppearedIntent != null)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@@ -130,7 +132,16 @@ class TaskFragmentContainer {
|
|||||||
mController = controller;
|
mController = controller;
|
||||||
mToken = new Binder("TaskFragmentContainer");
|
mToken = new Binder("TaskFragmentContainer");
|
||||||
mTaskContainer = taskContainer;
|
mTaskContainer = taskContainer;
|
||||||
taskContainer.mContainers.add(this);
|
if (pairedPrimaryContainer != null) {
|
||||||
|
if (pairedPrimaryContainer.getTaskContainer() != taskContainer) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"pairedPrimaryContainer must be in the same Task");
|
||||||
|
}
|
||||||
|
final int primaryIndex = taskContainer.mContainers.indexOf(pairedPrimaryContainer);
|
||||||
|
taskContainer.mContainers.add(primaryIndex + 1, this);
|
||||||
|
} else {
|
||||||
|
taskContainer.mContainers.add(this);
|
||||||
|
}
|
||||||
if (pendingAppearedActivity != null) {
|
if (pendingAppearedActivity != null) {
|
||||||
addPendingAppearedActivity(pendingAppearedActivity);
|
addPendingAppearedActivity(pendingAppearedActivity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class JetpackTaskFragmentOrganizerTest {
|
|||||||
public void testExpandTaskFragment() {
|
public void testExpandTaskFragment() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
new Intent(), taskContainer, mSplitController);
|
new Intent(), taskContainer, mSplitController, null /* pairedPrimaryContainer */);
|
||||||
final TaskFragmentInfo info = createMockInfo(container);
|
final TaskFragmentInfo info = createMockInfo(container);
|
||||||
mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
|
mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
|
||||||
container.setInfo(mTransaction, info);
|
container.setInfo(mTransaction, info);
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public class SplitControllerTest {
|
|||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
// tf1 has no running activity so is not active.
|
// tf1 has no running activity so is not active.
|
||||||
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
|
||||||
new Intent(), taskContainer, mSplitController);
|
new Intent(), taskContainer, mSplitController, null /* pairedPrimaryContainer */);
|
||||||
// tf2 has running activity so is active.
|
// tf2 has running activity so is active.
|
||||||
final TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
|
final TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
|
||||||
doReturn(1).when(tf2).getRunningActivityCount();
|
doReturn(1).when(tf2).getRunningActivityCount();
|
||||||
@@ -375,7 +375,7 @@ public class SplitControllerTest {
|
|||||||
final Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
intent, taskContainer, mSplitController);
|
intent, taskContainer, mSplitController, null /* pairedPrimaryContainer */);
|
||||||
final SplitController.ActivityStartMonitor monitor =
|
final SplitController.ActivityStartMonitor monitor =
|
||||||
mSplitController.getActivityStartMonitor();
|
mSplitController.getActivityStartMonitor();
|
||||||
|
|
||||||
@@ -609,7 +609,7 @@ public class SplitControllerTest {
|
|||||||
false /* isOnReparent */);
|
false /* isOnReparent */);
|
||||||
|
|
||||||
assertFalse(result);
|
assertFalse(result);
|
||||||
verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt());
|
verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -771,7 +771,7 @@ public class SplitControllerTest {
|
|||||||
false /* isOnReparent */);
|
false /* isOnReparent */);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt());
|
verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
|
||||||
verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
|
verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,7 +813,7 @@ public class SplitControllerTest {
|
|||||||
false /* isOnReparent */);
|
false /* isOnReparent */);
|
||||||
|
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt());
|
verify(mSplitController, never()).newContainer(any(), any(), any(), anyInt(), any());
|
||||||
verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
|
verify(mSplitController, never()).registerSplit(any(), any(), any(), any(), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public class TaskContainerTest {
|
|||||||
assertTrue(taskContainer.isEmpty());
|
assertTrue(taskContainer.isEmpty());
|
||||||
|
|
||||||
final TaskFragmentContainer tf = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer tf = new TaskFragmentContainer(null /* activity */,
|
||||||
new Intent(), taskContainer, mController);
|
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
|
|
||||||
assertFalse(taskContainer.isEmpty());
|
assertFalse(taskContainer.isEmpty());
|
||||||
|
|
||||||
@@ -138,11 +138,11 @@ public class TaskContainerTest {
|
|||||||
assertNull(taskContainer.getTopTaskFragmentContainer());
|
assertNull(taskContainer.getTopTaskFragmentContainer());
|
||||||
|
|
||||||
final TaskFragmentContainer tf0 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer tf0 = new TaskFragmentContainer(null /* activity */,
|
||||||
new Intent(), taskContainer, mController);
|
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
assertEquals(tf0, taskContainer.getTopTaskFragmentContainer());
|
assertEquals(tf0, taskContainer.getTopTaskFragmentContainer());
|
||||||
|
|
||||||
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
|
||||||
new Intent(), taskContainer, mController);
|
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
assertEquals(tf1, taskContainer.getTopTaskFragmentContainer());
|
assertEquals(tf1, taskContainer.getTopTaskFragmentContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,18 +94,21 @@ public class TaskFragmentContainerTest {
|
|||||||
|
|
||||||
// One of the activity and the intent must be non-null
|
// One of the activity and the intent must be non-null
|
||||||
assertThrows(IllegalArgumentException.class,
|
assertThrows(IllegalArgumentException.class,
|
||||||
() -> new TaskFragmentContainer(null, null, taskContainer, mController));
|
() -> new TaskFragmentContainer(null, null, taskContainer, mController,
|
||||||
|
null /* pairedPrimaryContainer */));
|
||||||
|
|
||||||
// One of the activity and the intent must be null.
|
// One of the activity and the intent must be null.
|
||||||
assertThrows(IllegalArgumentException.class,
|
assertThrows(IllegalArgumentException.class,
|
||||||
() -> new TaskFragmentContainer(mActivity, mIntent, taskContainer, mController));
|
() -> new TaskFragmentContainer(mActivity, mIntent, taskContainer, mController,
|
||||||
|
null /* pairedPrimaryContainer */));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFinish() {
|
public void testFinish() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(mActivity,
|
final TaskFragmentContainer container = new TaskFragmentContainer(mActivity,
|
||||||
null /* pendingAppearedIntent */, taskContainer, mController);
|
null /* pendingAppearedIntent */, taskContainer, mController,
|
||||||
|
null /* pairedPrimaryContainer */);
|
||||||
doReturn(container).when(mController).getContainerWithActivity(mActivity);
|
doReturn(container).when(mController).getContainerWithActivity(mActivity);
|
||||||
|
|
||||||
// Only remove the activity, but not clear the reference until appeared.
|
// Only remove the activity, but not clear the reference until appeared.
|
||||||
@@ -137,12 +140,14 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testFinish_notFinishActivityThatIsReparenting() {
|
public void testFinish_notFinishActivityThatIsReparenting() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container0 = new TaskFragmentContainer(mActivity,
|
final TaskFragmentContainer container0 = new TaskFragmentContainer(mActivity,
|
||||||
null /* pendingAppearedIntent */, taskContainer, mController);
|
null /* pendingAppearedIntent */, taskContainer, mController,
|
||||||
|
null /* pairedPrimaryContainer */);
|
||||||
final TaskFragmentInfo info = createMockTaskFragmentInfo(container0, mActivity);
|
final TaskFragmentInfo info = createMockTaskFragmentInfo(container0, mActivity);
|
||||||
container0.setInfo(mTransaction, 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,
|
||||||
|
null /* pairedPrimaryContainer */);
|
||||||
doReturn(container1).when(mController).getContainerWithActivity(mActivity);
|
doReturn(container1).when(mController).getContainerWithActivity(mActivity);
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
|
||||||
@@ -159,7 +164,8 @@ public class TaskFragmentContainerTest {
|
|||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
// Pending activity should be cleared when it has appeared on server side.
|
// Pending activity should be cleared when it has appeared on server side.
|
||||||
final TaskFragmentContainer pendingActivityContainer = new TaskFragmentContainer(mActivity,
|
final TaskFragmentContainer pendingActivityContainer = new TaskFragmentContainer(mActivity,
|
||||||
null /* pendingAppearedIntent */, taskContainer, mController);
|
null /* pendingAppearedIntent */, taskContainer, mController,
|
||||||
|
null /* pairedPrimaryContainer */);
|
||||||
|
|
||||||
assertTrue(pendingActivityContainer.mPendingAppearedActivities.contains(
|
assertTrue(pendingActivityContainer.mPendingAppearedActivities.contains(
|
||||||
mActivity.getActivityToken()));
|
mActivity.getActivityToken()));
|
||||||
@@ -172,7 +178,8 @@ public class TaskFragmentContainerTest {
|
|||||||
|
|
||||||
// Pending intent should be cleared when the container becomes non-empty.
|
// Pending intent should be cleared when the container becomes non-empty.
|
||||||
final TaskFragmentContainer pendingIntentContainer = new TaskFragmentContainer(
|
final TaskFragmentContainer pendingIntentContainer = new TaskFragmentContainer(
|
||||||
null /* pendingAppearedActivity */, mIntent, taskContainer, mController);
|
null /* pendingAppearedActivity */, mIntent, taskContainer, mController,
|
||||||
|
null /* pairedPrimaryContainer */);
|
||||||
|
|
||||||
assertEquals(mIntent, pendingIntentContainer.getPendingAppearedIntent());
|
assertEquals(mIntent, pendingIntentContainer.getPendingAppearedIntent());
|
||||||
|
|
||||||
@@ -187,7 +194,7 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testIsWaitingActivityAppear() {
|
public void testIsWaitingActivityAppear() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
|
|
||||||
assertTrue(container.isWaitingActivityAppear());
|
assertTrue(container.isWaitingActivityAppear());
|
||||||
|
|
||||||
@@ -209,7 +216,7 @@ public class TaskFragmentContainerTest {
|
|||||||
doNothing().when(mController).onTaskFragmentAppearEmptyTimeout(any(), any());
|
doNothing().when(mController).onTaskFragmentAppearEmptyTimeout(any(), any());
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
|
|
||||||
assertNull(container.mAppearEmptyTimeout);
|
assertNull(container.mAppearEmptyTimeout);
|
||||||
|
|
||||||
@@ -249,7 +256,7 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testCollectNonFinishingActivities() {
|
public void testCollectNonFinishingActivities() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
List<Activity> activities = container.collectNonFinishingActivities();
|
List<Activity> activities = container.collectNonFinishingActivities();
|
||||||
|
|
||||||
assertTrue(activities.isEmpty());
|
assertTrue(activities.isEmpty());
|
||||||
@@ -277,7 +284,7 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testAddPendingActivity() {
|
public void testAddPendingActivity() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
container.addPendingAppearedActivity(mActivity);
|
container.addPendingAppearedActivity(mActivity);
|
||||||
|
|
||||||
assertEquals(1, container.collectNonFinishingActivities().size());
|
assertEquals(1, container.collectNonFinishingActivities().size());
|
||||||
@@ -291,9 +298,9 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testIsAbove() {
|
public void testIsAbove() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container0 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container0 = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
|
|
||||||
assertTrue(container1.isAbove(container0));
|
assertTrue(container1.isAbove(container0));
|
||||||
assertFalse(container0.isAbove(container1));
|
assertFalse(container0.isAbove(container1));
|
||||||
@@ -303,7 +310,7 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testGetBottomMostActivity() {
|
public void testGetBottomMostActivity() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
container.addPendingAppearedActivity(mActivity);
|
container.addPendingAppearedActivity(mActivity);
|
||||||
|
|
||||||
assertEquals(mActivity, container.getBottomMostActivity());
|
assertEquals(mActivity, container.getBottomMostActivity());
|
||||||
@@ -320,7 +327,7 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testOnActivityDestroyed() {
|
public void testOnActivityDestroyed() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer(mController);
|
final TaskContainer taskContainer = createTestTaskContainer(mController);
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
container.addPendingAppearedActivity(mActivity);
|
container.addPendingAppearedActivity(mActivity);
|
||||||
final List<IBinder> activities = new ArrayList<>();
|
final List<IBinder> activities = new ArrayList<>();
|
||||||
activities.add(mActivity.getActivityToken());
|
activities.add(mActivity.getActivityToken());
|
||||||
@@ -340,7 +347,7 @@ public class TaskFragmentContainerTest {
|
|||||||
// True if no info set.
|
// True if no info set.
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
spyOn(taskContainer);
|
spyOn(taskContainer);
|
||||||
doReturn(true).when(taskContainer).isVisible();
|
doReturn(true).when(taskContainer).isVisible();
|
||||||
|
|
||||||
@@ -403,7 +410,7 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testHasAppearedActivity() {
|
public void testHasAppearedActivity() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
container.addPendingAppearedActivity(mActivity);
|
container.addPendingAppearedActivity(mActivity);
|
||||||
|
|
||||||
assertFalse(container.hasAppearedActivity(mActivity.getActivityToken()));
|
assertFalse(container.hasAppearedActivity(mActivity.getActivityToken()));
|
||||||
@@ -420,7 +427,7 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testHasPendingAppearedActivity() {
|
public void testHasPendingAppearedActivity() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
container.addPendingAppearedActivity(mActivity);
|
container.addPendingAppearedActivity(mActivity);
|
||||||
|
|
||||||
assertTrue(container.hasPendingAppearedActivity(mActivity.getActivityToken()));
|
assertTrue(container.hasPendingAppearedActivity(mActivity.getActivityToken()));
|
||||||
@@ -437,9 +444,9 @@ public class TaskFragmentContainerTest {
|
|||||||
public void testHasActivity() {
|
public void testHasActivity() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer(mController);
|
final TaskContainer taskContainer = createTestTaskContainer(mController);
|
||||||
final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
final TaskFragmentContainer container2 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer container2 = new TaskFragmentContainer(null /* activity */,
|
||||||
mIntent, taskContainer, mController);
|
mIntent, taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
|
|
||||||
// Activity is pending appeared on container2.
|
// Activity is pending appeared on container2.
|
||||||
container2.addPendingAppearedActivity(mActivity);
|
container2.addPendingAppearedActivity(mActivity);
|
||||||
@@ -472,6 +479,27 @@ public class TaskFragmentContainerTest {
|
|||||||
assertTrue(container2.hasActivity(mActivity.getActivityToken()));
|
assertTrue(container2.hasActivity(mActivity.getActivityToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNewContainerWithPairedPrimaryContainer() {
|
||||||
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
|
final TaskFragmentContainer tf0 = new TaskFragmentContainer(
|
||||||
|
null /* pendingAppearedActivity */, new Intent(), taskContainer, mController,
|
||||||
|
null /* pairedPrimaryTaskFragment */);
|
||||||
|
final TaskFragmentContainer tf1 = new TaskFragmentContainer(
|
||||||
|
null /* pendingAppearedActivity */, new Intent(), taskContainer, mController,
|
||||||
|
null /* pairedPrimaryTaskFragment */);
|
||||||
|
taskContainer.mContainers.add(tf0);
|
||||||
|
taskContainer.mContainers.add(tf1);
|
||||||
|
|
||||||
|
// When tf2 is created with using tf0 as pairedPrimaryContainer, tf2 should be inserted
|
||||||
|
// right above tf0.
|
||||||
|
final TaskFragmentContainer tf2 = new TaskFragmentContainer(
|
||||||
|
null /* pendingAppearedActivity */, new Intent(), taskContainer, mController, tf0);
|
||||||
|
assertEquals(0, taskContainer.indexOf(tf0));
|
||||||
|
assertEquals(1, taskContainer.indexOf(tf2));
|
||||||
|
assertEquals(2, taskContainer.indexOf(tf1));
|
||||||
|
}
|
||||||
|
|
||||||
/** Creates a mock activity in the organizer process. */
|
/** Creates a mock activity in the organizer process. */
|
||||||
private Activity createMockActivity() {
|
private Activity createMockActivity() {
|
||||||
final Activity activity = mock(Activity.class);
|
final Activity activity = mock(Activity.class);
|
||||||
|
|||||||
@@ -1891,7 +1891,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
// actions.
|
// actions.
|
||||||
taskFragment.setTaskFragmentOrganizer(creationParams.getOrganizer(),
|
taskFragment.setTaskFragmentOrganizer(creationParams.getOrganizer(),
|
||||||
ownerActivity.getUid(), ownerActivity.info.processName);
|
ownerActivity.getUid(), ownerActivity.info.processName);
|
||||||
ownerTask.addChild(taskFragment, POSITION_TOP);
|
final int position;
|
||||||
|
if (creationParams.getPairedPrimaryFragmentToken() != null) {
|
||||||
|
// When there is a paired primary TaskFragment, we want to place the new TaskFragment
|
||||||
|
// right above the paired one to make sure there is no other window in between.
|
||||||
|
final TaskFragment pairedPrimaryTaskFragment = getTaskFragment(
|
||||||
|
creationParams.getPairedPrimaryFragmentToken());
|
||||||
|
final int pairedPosition = ownerTask.mChildren.indexOf(pairedPrimaryTaskFragment);
|
||||||
|
position = pairedPosition != -1 ? pairedPosition + 1 : POSITION_TOP;
|
||||||
|
} else {
|
||||||
|
position = POSITION_TOP;
|
||||||
|
}
|
||||||
|
ownerTask.addChild(taskFragment, position);
|
||||||
taskFragment.setWindowingMode(creationParams.getWindowingMode());
|
taskFragment.setWindowingMode(creationParams.getWindowingMode());
|
||||||
taskFragment.setBounds(creationParams.getInitialBounds());
|
taskFragment.setBounds(creationParams.getInitialBounds());
|
||||||
mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
|
mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
|
||||||
|
|||||||
@@ -552,10 +552,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
|||||||
@Test
|
@Test
|
||||||
public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() {
|
public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() {
|
||||||
final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
|
final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent);
|
||||||
final IBinder fragmentToken = new Binder();
|
|
||||||
|
|
||||||
// Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
|
// Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
|
||||||
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken);
|
createTaskFragmentFromOrganizer(mTransaction, ownerActivity, mFragmentToken);
|
||||||
mTransaction.startActivityInTaskFragment(
|
mTransaction.startActivityInTaskFragment(
|
||||||
mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */);
|
mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */);
|
||||||
mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class));
|
mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class));
|
||||||
@@ -564,7 +563,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
|||||||
assertApplyTransactionAllowed(mTransaction);
|
assertApplyTransactionAllowed(mTransaction);
|
||||||
|
|
||||||
// Successfully created a TaskFragment.
|
// Successfully created a TaskFragment.
|
||||||
final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
|
final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(
|
||||||
|
mFragmentToken);
|
||||||
assertNotNull(taskFragment);
|
assertNotNull(taskFragment);
|
||||||
assertEquals(ownerActivity.getTask(), taskFragment.getTask());
|
assertEquals(ownerActivity.getTask(), taskFragment.getTask());
|
||||||
}
|
}
|
||||||
@@ -702,6 +702,40 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
|||||||
assertNotNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
|
assertNotNull(mWindowOrganizerController.getTaskFragment(fragmentToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyTransaction_createTaskFragment_withPairedPrimaryFragmentToken() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
|
mTaskFragment = new TaskFragmentBuilder(mAtm)
|
||||||
|
.setParentTask(task)
|
||||||
|
.setFragmentToken(mFragmentToken)
|
||||||
|
.createActivityCount(1)
|
||||||
|
.build();
|
||||||
|
mWindowOrganizerController.mLaunchTaskFragments.put(mFragmentToken, mTaskFragment);
|
||||||
|
final ActivityRecord activityOnTop = createActivityRecord(task);
|
||||||
|
final int uid = Binder.getCallingUid();
|
||||||
|
activityOnTop.info.applicationInfo.uid = uid;
|
||||||
|
activityOnTop.getTask().effectiveUid = uid;
|
||||||
|
final IBinder fragmentToken1 = new Binder();
|
||||||
|
final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
|
||||||
|
mOrganizerToken, fragmentToken1, activityOnTop.token)
|
||||||
|
.setPairedPrimaryFragmentToken(mFragmentToken)
|
||||||
|
.build();
|
||||||
|
mTransaction.setTaskFragmentOrganizer(mIOrganizer);
|
||||||
|
mTransaction.createTaskFragment(params);
|
||||||
|
assertApplyTransactionAllowed(mTransaction);
|
||||||
|
|
||||||
|
// Successfully created a TaskFragment.
|
||||||
|
final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(
|
||||||
|
fragmentToken1);
|
||||||
|
assertNotNull(taskFragment);
|
||||||
|
// The new TaskFragment should be positioned right above the paired TaskFragment.
|
||||||
|
assertEquals(task.mChildren.indexOf(mTaskFragment) + 1,
|
||||||
|
task.mChildren.indexOf(taskFragment));
|
||||||
|
// The top activity should remain on top.
|
||||||
|
assertEquals(task.mChildren.indexOf(taskFragment) + 1,
|
||||||
|
task.mChildren.indexOf(activityOnTop));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApplyTransaction_enforceHierarchyChange_reparentChildren() {
|
public void testApplyTransaction_enforceHierarchyChange_reparentChildren() {
|
||||||
doReturn(true).when(mTaskFragment).isAttached();
|
doReturn(true).when(mTaskFragment).isAttached();
|
||||||
|
|||||||
Reference in New Issue
Block a user