Merge "[3/n] Pin ActivityStack" into udc-qpr-dev
This commit is contained in:
@@ -48,7 +48,7 @@ public class WindowExtensionsImpl implements WindowExtensions {
|
|||||||
// TODO(b/241126279) Introduce constants to better version functionality
|
// TODO(b/241126279) Introduce constants to better version functionality
|
||||||
@Override
|
@Override
|
||||||
public int getVendorApiLevel() {
|
public int getVendorApiLevel() {
|
||||||
return 3;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import androidx.window.extensions.core.util.function.Function;
|
|||||||
*/
|
*/
|
||||||
class SplitContainer {
|
class SplitContainer {
|
||||||
@NonNull
|
@NonNull
|
||||||
private final TaskFragmentContainer mPrimaryContainer;
|
private TaskFragmentContainer mPrimaryContainer;
|
||||||
@NonNull
|
@NonNull
|
||||||
private final TaskFragmentContainer mSecondaryContainer;
|
private final TaskFragmentContainer mSecondaryContainer;
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -46,17 +46,35 @@ class SplitContainer {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final IBinder mToken;
|
private final IBinder mToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the selection of which container is primary can be changed at runtime. Runtime
|
||||||
|
* updates is currently possible only for {@link SplitPinContainer}
|
||||||
|
*
|
||||||
|
* @see SplitPinContainer
|
||||||
|
*/
|
||||||
|
private final boolean mIsPrimaryContainerMutable;
|
||||||
|
|
||||||
SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
|
SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
|
||||||
@NonNull Activity primaryActivity,
|
@NonNull Activity primaryActivity,
|
||||||
@NonNull TaskFragmentContainer secondaryContainer,
|
@NonNull TaskFragmentContainer secondaryContainer,
|
||||||
@NonNull SplitRule splitRule,
|
@NonNull SplitRule splitRule,
|
||||||
@NonNull SplitAttributes splitAttributes) {
|
@NonNull SplitAttributes splitAttributes) {
|
||||||
|
this(primaryContainer, primaryActivity, secondaryContainer, splitRule, splitAttributes,
|
||||||
|
false /* isPrimaryContainerMutable */);
|
||||||
|
}
|
||||||
|
|
||||||
|
SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
|
||||||
|
@NonNull Activity primaryActivity,
|
||||||
|
@NonNull TaskFragmentContainer secondaryContainer,
|
||||||
|
@NonNull SplitRule splitRule,
|
||||||
|
@NonNull SplitAttributes splitAttributes, boolean isPrimaryContainerMutable) {
|
||||||
mPrimaryContainer = primaryContainer;
|
mPrimaryContainer = primaryContainer;
|
||||||
mSecondaryContainer = secondaryContainer;
|
mSecondaryContainer = secondaryContainer;
|
||||||
mSplitRule = splitRule;
|
mSplitRule = splitRule;
|
||||||
mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
|
mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
|
||||||
mCurrentSplitAttributes = splitAttributes;
|
mCurrentSplitAttributes = splitAttributes;
|
||||||
mToken = new Binder("SplitContainer");
|
mToken = new Binder("SplitContainer");
|
||||||
|
mIsPrimaryContainerMutable = isPrimaryContainerMutable;
|
||||||
|
|
||||||
if (shouldFinishPrimaryWithSecondary(splitRule)) {
|
if (shouldFinishPrimaryWithSecondary(splitRule)) {
|
||||||
if (mPrimaryContainer.getRunningActivityCount() == 1
|
if (mPrimaryContainer.getRunningActivityCount() == 1
|
||||||
@@ -74,6 +92,13 @@ class SplitContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPrimaryContainer(@NonNull TaskFragmentContainer primaryContainer) {
|
||||||
|
if (!mIsPrimaryContainerMutable) {
|
||||||
|
throw new IllegalStateException("Cannot update primary TaskFragmentContainer");
|
||||||
|
}
|
||||||
|
mPrimaryContainer = primaryContainer;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
TaskFragmentContainer getPrimaryContainer() {
|
TaskFragmentContainer getPrimaryContainer() {
|
||||||
return mPrimaryContainer;
|
return mPrimaryContainer;
|
||||||
|
|||||||
@@ -212,6 +212,56 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean pinTopActivityStack(int taskId, @NonNull SplitPinRule splitPinRule) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
final TaskContainer task = getTaskContainer(taskId);
|
||||||
|
if (task == null) {
|
||||||
|
Log.e(TAG, "Cannot find the task for id: " + taskId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TaskFragmentContainer topContainer =
|
||||||
|
task.getTopNonFinishingTaskFragmentContainer();
|
||||||
|
// Cannot pin the TaskFragment if no other TaskFragment behind it.
|
||||||
|
if (topContainer == null || task.indexOf(topContainer) <= 0) {
|
||||||
|
Log.w(TAG, "Cannot find an ActivityStack to pin or split");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Abort if the top container is already pinned.
|
||||||
|
if (task.getSplitPinContainer() != null) {
|
||||||
|
Log.w(TAG, "There is already a pinned ActivityStack.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a valid adjacent TaskFragmentContainer
|
||||||
|
final TaskFragmentContainer primaryContainer =
|
||||||
|
task.getNonFinishingTaskFragmentContainerBelow(topContainer);
|
||||||
|
if (primaryContainer == null) {
|
||||||
|
Log.w(TAG, "Cannot find another ActivityStack to split");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers a Split
|
||||||
|
final SplitPinContainer splitPinContainer = new SplitPinContainer(primaryContainer,
|
||||||
|
topContainer, splitPinRule, splitPinRule.getDefaultSplitAttributes());
|
||||||
|
task.addSplitContainer(splitPinContainer);
|
||||||
|
|
||||||
|
// Updates the Split
|
||||||
|
final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
|
||||||
|
final WindowContainerTransaction wct = transactionRecord.getTransaction();
|
||||||
|
mPresenter.updateSplitContainer(splitPinContainer, wct);
|
||||||
|
transactionRecord.apply(false /* shouldApplyIndependently */);
|
||||||
|
updateCallbackIfNecessary();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unpinTopActivityStack(int taskId){
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSplitAttributesCalculator(
|
public void setSplitAttributesCalculator(
|
||||||
@NonNull Function<SplitAttributesCalculatorParams, SplitAttributes> calculator) {
|
@NonNull Function<SplitAttributesCalculatorParams, SplitAttributes> calculator) {
|
||||||
@@ -672,7 +722,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
if (targetContainer == null) {
|
if (targetContainer == null) {
|
||||||
// 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.
|
||||||
targetContainer = taskContainer.getTopTaskFragmentContainer();
|
targetContainer = taskContainer.getTopNonFinishingTaskFragmentContainer();
|
||||||
}
|
}
|
||||||
if (targetContainer == null) {
|
if (targetContainer == null) {
|
||||||
return;
|
return;
|
||||||
@@ -791,7 +841,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
|
|
||||||
final TaskFragmentContainer container = getContainerWithActivity(activity);
|
final TaskFragmentContainer container = getContainerWithActivity(activity);
|
||||||
if (!isOnReparent && container != null
|
if (!isOnReparent && container != null
|
||||||
&& container.getTaskContainer().getTopTaskFragmentContainer() != container) {
|
&& container.getTaskContainer().getTopNonFinishingTaskFragmentContainer()
|
||||||
|
!= container) {
|
||||||
// Do not resolve if the launched activity is not the top-most container in the Task.
|
// Do not resolve if the launched activity is not the top-most container in the Task.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -888,7 +939,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
if (taskContainer == null) {
|
if (taskContainer == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final TaskFragmentContainer targetContainer = taskContainer.getTopTaskFragmentContainer();
|
final TaskFragmentContainer targetContainer =
|
||||||
|
taskContainer.getTopNonFinishingTaskFragmentContainer();
|
||||||
if (targetContainer == null) {
|
if (targetContainer == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1213,11 +1265,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
|
|
||||||
// 3. Whether the top activity (if any) should be split with the new activity intent.
|
// 3. Whether the top activity (if any) should be split with the new activity intent.
|
||||||
final TaskContainer taskContainer = getTaskContainer(taskId);
|
final TaskContainer taskContainer = getTaskContainer(taskId);
|
||||||
if (taskContainer == null || taskContainer.getTopTaskFragmentContainer() == null) {
|
if (taskContainer == null
|
||||||
|
|| taskContainer.getTopNonFinishingTaskFragmentContainer() == null) {
|
||||||
// There is no other activity in the Task to check split with.
|
// There is no other activity in the Task to check split with.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final TaskFragmentContainer topContainer = taskContainer.getTopTaskFragmentContainer();
|
final TaskFragmentContainer topContainer =
|
||||||
|
taskContainer.getTopNonFinishingTaskFragmentContainer();
|
||||||
final Activity topActivity = topContainer.getTopNonFinishingActivity();
|
final Activity topActivity = topContainer.getTopNonFinishingActivity();
|
||||||
if (topActivity != null && topActivity != launchingActivity) {
|
if (topActivity != null && topActivity != launchingActivity) {
|
||||||
final TaskFragmentContainer container = getSecondaryContainerForSplitIfAny(wct,
|
final TaskFragmentContainer container = getSecondaryContainerForSplitIfAny(wct,
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package androidx.window.extensions.embedding;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client-side descriptor of a split that holds two containers while the secondary
|
||||||
|
* container is pinned on top of the Task and the primary container is the container that is
|
||||||
|
* currently below the secondary container. The primary container could be updated to
|
||||||
|
* another container whenever the existing primary container is removed or no longer
|
||||||
|
* be the container that's right behind the secondary container.
|
||||||
|
*/
|
||||||
|
class SplitPinContainer extends SplitContainer {
|
||||||
|
|
||||||
|
SplitPinContainer(@NonNull TaskFragmentContainer primaryContainer,
|
||||||
|
@NonNull TaskFragmentContainer secondaryContainer,
|
||||||
|
@NonNull SplitPinRule splitPinRule,
|
||||||
|
@NonNull SplitAttributes splitAttributes) {
|
||||||
|
super(primaryContainer, primaryContainer.getTopNonFinishingActivity(), secondaryContainer,
|
||||||
|
splitPinRule, splitAttributes, true /* isPrimaryContainerMutable */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SplitPinContainer{"
|
||||||
|
+ " primaryContainer=" + getPrimaryContainer()
|
||||||
|
+ " secondaryContainer=" + getSecondaryContainer()
|
||||||
|
+ " splitPinRule=" + getSplitRule()
|
||||||
|
+ " splitAttributes" + getCurrentSplitAttributes()
|
||||||
|
+ "}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -336,10 +336,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
// value.
|
// value.
|
||||||
final SplitRule rule = splitContainer.getSplitRule();
|
final SplitRule rule = splitContainer.getSplitRule();
|
||||||
final TaskFragmentContainer primaryContainer = splitContainer.getPrimaryContainer();
|
final TaskFragmentContainer primaryContainer = splitContainer.getPrimaryContainer();
|
||||||
final Activity activity = primaryContainer.getTopNonFinishingActivity();
|
|
||||||
if (activity == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final TaskContainer taskContainer = splitContainer.getTaskContainer();
|
final TaskContainer taskContainer = splitContainer.getTaskContainer();
|
||||||
final TaskProperties taskProperties = taskContainer.getTaskProperties();
|
final TaskProperties taskProperties = taskContainer.getTaskProperties();
|
||||||
final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
|
final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ class TaskContainer {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final List<SplitContainer> mSplitContainers = new ArrayList<>();
|
private final List<SplitContainer> mSplitContainers = new ArrayList<>();
|
||||||
|
|
||||||
|
/** Active pin split pair in this Task. */
|
||||||
|
@Nullable
|
||||||
|
private SplitPinContainer mSplitPinContainer;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Configuration mConfiguration;
|
private final Configuration mConfiguration;
|
||||||
|
|
||||||
@@ -174,11 +178,28 @@ class TaskContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
TaskFragmentContainer getTopTaskFragmentContainer() {
|
TaskFragmentContainer getTopNonFinishingTaskFragmentContainer() {
|
||||||
if (mContainers.isEmpty()) {
|
for (int i = mContainers.size() - 1; i >= 0; i--) {
|
||||||
|
final TaskFragmentContainer container = mContainers.get(i);
|
||||||
|
if (!container.isFinished()) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return mContainers.get(mContainers.size() - 1);
|
|
||||||
|
/** Gets a non-finishing container below the given one. */
|
||||||
|
@Nullable
|
||||||
|
TaskFragmentContainer getNonFinishingTaskFragmentContainerBelow(
|
||||||
|
@NonNull TaskFragmentContainer current) {
|
||||||
|
final int index = mContainers.indexOf(current);
|
||||||
|
for (int i = index - 1; i >= 0; i--) {
|
||||||
|
final TaskFragmentContainer container = mContainers.get(i);
|
||||||
|
if (!container.isFinished()) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -217,31 +238,57 @@ class TaskContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addSplitContainer(@NonNull SplitContainer splitContainer) {
|
void addSplitContainer(@NonNull SplitContainer splitContainer) {
|
||||||
|
if (splitContainer instanceof SplitPinContainer) {
|
||||||
|
mSplitPinContainer = (SplitPinContainer) splitContainer;
|
||||||
mSplitContainers.add(splitContainer);
|
mSplitContainers.add(splitContainer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keeps the SplitPinContainer on the top of the list.
|
||||||
|
mSplitContainers.remove(mSplitPinContainer);
|
||||||
|
mSplitContainers.add(splitContainer);
|
||||||
|
if (mSplitPinContainer != null) {
|
||||||
|
mSplitContainers.add(mSplitPinContainer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeSplitContainers(@NonNull List<SplitContainer> containers) {
|
void removeSplitContainers(@NonNull List<SplitContainer> containers) {
|
||||||
mSplitContainers.removeAll(containers);
|
mSplitContainers.removeAll(containers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeSplitPinContainer() {
|
||||||
|
mSplitContainers.remove(mSplitPinContainer);
|
||||||
|
mSplitPinContainer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
SplitPinContainer getSplitPinContainer() {
|
||||||
|
return mSplitPinContainer;
|
||||||
|
}
|
||||||
|
|
||||||
void addTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
|
void addTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
|
||||||
mContainers.add(taskFragmentContainer);
|
mContainers.add(taskFragmentContainer);
|
||||||
|
onTaskFragmentContainerUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTaskFragmentContainer(int index, @NonNull TaskFragmentContainer taskFragmentContainer) {
|
void addTaskFragmentContainer(int index, @NonNull TaskFragmentContainer taskFragmentContainer) {
|
||||||
mContainers.add(index, taskFragmentContainer);
|
mContainers.add(index, taskFragmentContainer);
|
||||||
|
onTaskFragmentContainerUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
|
void removeTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
|
||||||
mContainers.remove(taskFragmentContainer);
|
mContainers.remove(taskFragmentContainer);
|
||||||
|
onTaskFragmentContainerUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeTaskFragmentContainers(@NonNull List<TaskFragmentContainer> taskFragmentContainer) {
|
void removeTaskFragmentContainers(@NonNull List<TaskFragmentContainer> taskFragmentContainer) {
|
||||||
mContainers.removeAll(taskFragmentContainer);
|
mContainers.removeAll(taskFragmentContainer);
|
||||||
|
onTaskFragmentContainerUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearTaskFragmentContainer() {
|
void clearTaskFragmentContainer() {
|
||||||
mContainers.clear();
|
mContainers.clear();
|
||||||
|
onTaskFragmentContainerUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -254,6 +301,34 @@ class TaskContainer {
|
|||||||
return mContainers;
|
return mContainers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onTaskFragmentContainerUpdated() {
|
||||||
|
if (mSplitPinContainer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TaskFragmentContainer pinnedContainer = mSplitPinContainer.getSecondaryContainer();
|
||||||
|
final int index = mContainers.indexOf(pinnedContainer);
|
||||||
|
if (index <= 0) {
|
||||||
|
removeSplitPinContainer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the pinned container is top-most.
|
||||||
|
if (index != mContainers.size() - 1) {
|
||||||
|
mContainers.remove(pinnedContainer);
|
||||||
|
mContainers.add(pinnedContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the primary container adjacent to the pinned container if needed.
|
||||||
|
final TaskFragmentContainer adjacentContainer =
|
||||||
|
getNonFinishingTaskFragmentContainerBelow(pinnedContainer);
|
||||||
|
if (adjacentContainer == null) {
|
||||||
|
removeSplitPinContainer();
|
||||||
|
} else if (mSplitPinContainer.getPrimaryContainer() != adjacentContainer) {
|
||||||
|
mSplitPinContainer.setPrimaryContainer(adjacentContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Adds the descriptors of split states in this Task to {@code outSplitStates}. */
|
/** Adds the descriptors of split states in this Task to {@code outSplitStates}. */
|
||||||
void getSplitStates(@NonNull List<SplitInfo> outSplitStates) {
|
void getSplitStates(@NonNull List<SplitInfo> outSplitStates) {
|
||||||
for (SplitContainer container : mSplitContainers) {
|
for (SplitContainer container : mSplitContainers) {
|
||||||
|
|||||||
@@ -1462,6 +1462,51 @@ public class SplitControllerTest {
|
|||||||
verify(testRecord).apply(eq(false));
|
verify(testRecord).apply(eq(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPinTopActivityStack() {
|
||||||
|
// Create two activities.
|
||||||
|
final Activity primaryActivity = createMockActivity();
|
||||||
|
final Activity secondaryActivity = createMockActivity();
|
||||||
|
|
||||||
|
// Unable to pin if not being embedded.
|
||||||
|
SplitPinRule splitPinRule = new SplitPinRule.Builder(new SplitAttributes.Builder().build(),
|
||||||
|
parentWindowMetrics -> true /* parentWindowMetricsPredicate */).build();
|
||||||
|
assertFalse(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
|
||||||
|
|
||||||
|
// Split the two activities.
|
||||||
|
addSplitTaskFragments(primaryActivity, secondaryActivity);
|
||||||
|
final TaskFragmentContainer primaryContainer =
|
||||||
|
mSplitController.getContainerWithActivity(primaryActivity);
|
||||||
|
spyOn(primaryContainer);
|
||||||
|
|
||||||
|
// Unable to pin if no valid TaskFragment.
|
||||||
|
doReturn(true).when(primaryContainer).isFinished();
|
||||||
|
assertFalse(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
|
||||||
|
|
||||||
|
// Otherwise, should pin successfully.
|
||||||
|
doReturn(false).when(primaryContainer).isFinished();
|
||||||
|
assertTrue(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
|
||||||
|
|
||||||
|
// Unable to pin if there is already a pinned TaskFragment
|
||||||
|
assertFalse(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
|
||||||
|
|
||||||
|
// Unable to pin on an unknown Task.
|
||||||
|
assertFalse(mSplitController.pinTopActivityStack(TASK_ID + 1, splitPinRule));
|
||||||
|
|
||||||
|
// Gets the current size of all the SplitContainers.
|
||||||
|
final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
|
||||||
|
final int splitContainerCount = taskContainer.getSplitContainers().size();
|
||||||
|
|
||||||
|
// Create another activity and split with primary activity.
|
||||||
|
final Activity thirdActivity = createMockActivity();
|
||||||
|
addSplitTaskFragments(primaryActivity, thirdActivity);
|
||||||
|
|
||||||
|
// Ensure another SplitContainer is added and the pinned TaskFragment still on top
|
||||||
|
assertTrue(taskContainer.getSplitContainers().size() == splitContainerCount + +1);
|
||||||
|
assertTrue(mSplitController.getTopActiveContainer(TASK_ID).getTopNonFinishingActivity()
|
||||||
|
== secondaryActivity);
|
||||||
|
}
|
||||||
|
|
||||||
/** Creates a mock activity in the organizer process. */
|
/** Creates a mock activity in the organizer process. */
|
||||||
private Activity createMockActivity() {
|
private Activity createMockActivity() {
|
||||||
return createMockActivity(TASK_ID);
|
return createMockActivity(TASK_ID);
|
||||||
|
|||||||
@@ -135,15 +135,15 @@ public class TaskContainerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetTopTaskFragmentContainer() {
|
public void testGetTopTaskFragmentContainer() {
|
||||||
final TaskContainer taskContainer = createTestTaskContainer();
|
final TaskContainer taskContainer = createTestTaskContainer();
|
||||||
assertNull(taskContainer.getTopTaskFragmentContainer());
|
assertNull(taskContainer.getTopNonFinishingTaskFragmentContainer());
|
||||||
|
|
||||||
final TaskFragmentContainer tf0 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer tf0 = new TaskFragmentContainer(null /* activity */,
|
||||||
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
|
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
assertEquals(tf0, taskContainer.getTopTaskFragmentContainer());
|
assertEquals(tf0, taskContainer.getTopNonFinishingTaskFragmentContainer());
|
||||||
|
|
||||||
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
|
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
|
||||||
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
|
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
|
||||||
assertEquals(tf1, taskContainer.getTopTaskFragmentContainer());
|
assertEquals(tf1, taskContainer.getTopNonFinishingTaskFragmentContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user