Merge "[4/n] Pin ActivityStack" into udc-qpr-dev

This commit is contained in:
Louis Chang
2023-07-13 00:25:00 +00:00
committed by Android (Google) Code Review
6 changed files with 85 additions and 5 deletions

View File

@@ -73,6 +73,13 @@ public final class TaskFragmentOperation implements Parcelable {
/** Sets the relative bounds with {@link WindowContainerTransaction#setRelativeBounds}. */
public static final int OP_TYPE_SET_RELATIVE_BOUNDS = 9;
/**
* Reorders the TaskFragment to be the front-most TaskFragment in the Task.
* Note that there could still have other WindowContainer on top of the front-most
* TaskFragment, such as a non-embedded Activity.
*/
public static final int OP_TYPE_REORDER_TO_FRONT = 10;
@IntDef(prefix = { "OP_TYPE_" }, value = {
OP_TYPE_UNKNOWN,
OP_TYPE_CREATE_TASK_FRAGMENT,
@@ -84,7 +91,8 @@ public final class TaskFragmentOperation implements Parcelable {
OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT,
OP_TYPE_SET_COMPANION_TASK_FRAGMENT,
OP_TYPE_SET_ANIMATION_PARAMS,
OP_TYPE_SET_RELATIVE_BOUNDS
OP_TYPE_SET_RELATIVE_BOUNDS,
OP_TYPE_REORDER_TO_FRONT
})
@Retention(RetentionPolicy.SOURCE)
public @interface OperationType {}

View File

@@ -1621,6 +1621,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// background.
return;
}
final SplitContainer splitContainer = getActiveSplitForContainer(container);
if (splitContainer instanceof SplitPinContainer
&& updateSplitContainerIfNeeded(splitContainer, wct, null /* splitAttributes */)) {
// A SplitPinContainer exists and is updated.
return;
}
if (launchPlaceholderIfNecessary(wct, container)) {
// Placeholder was launched, the positions will be updated when the activity is added
// to the secondary container.
@@ -1633,7 +1639,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// If the info is not available yet the task fragment will be expanded when it's ready
return;
}
SplitContainer splitContainer = getActiveSplitForContainer(container);
if (splitContainer == null) {
return;
}

View File

@@ -17,6 +17,7 @@
package androidx.window.extensions.embedding;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT;
import android.app.Activity;
import android.app.ActivityThread;
@@ -39,6 +40,7 @@ import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.window.TaskFragmentAnimationParams;
import android.window.TaskFragmentCreationParams;
import android.window.TaskFragmentOperation;
import android.window.WindowContainerTransaction;
import androidx.annotation.IntDef;
@@ -420,6 +422,16 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
container.setLastRequestedBounds(fragmentOptions.getInitialRelativeBounds());
container.setLastRequestedWindowingMode(fragmentOptions.getWindowingMode());
super.createTaskFragment(wct, fragmentOptions);
// Reorders the pinned TaskFragment to front to ensure it is the front-most TaskFragment.
final SplitPinContainer pinnedContainer =
container.getTaskContainer().getSplitPinContainer();
if (pinnedContainer != null) {
final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
OP_TYPE_REORDER_TO_FRONT).build();
wct.addTaskFragmentOperation(
pinnedContainer.getSecondaryContainer().getTaskFragmentToken(), operation);
}
}
@Override

View File

@@ -307,14 +307,14 @@ class TaskContainer {
}
final TaskFragmentContainer pinnedContainer = mSplitPinContainer.getSecondaryContainer();
final int index = mContainers.indexOf(pinnedContainer);
if (index <= 0) {
final int pinnedContainerIndex = mContainers.indexOf(pinnedContainer);
if (pinnedContainerIndex <= 0) {
removeSplitPinContainer();
return;
}
// Ensure the pinned container is top-most.
if (index != mContainers.size() - 1) {
if (pinnedContainerIndex != mContainers.size() - 1) {
mContainers.remove(pinnedContainer);
mContainers.add(pinnedContainer);
}

View File

@@ -24,6 +24,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT;
import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS;
@@ -1335,6 +1336,19 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
taskFragment.setAnimationParams(animationParams);
break;
}
case OP_TYPE_REORDER_TO_FRONT: {
final Task task = taskFragment.getTask();
if (task != null) {
final TaskFragment topTaskFragment = task.getTaskFragment(
tf -> tf.asTask() == null);
if (topTaskFragment != null && topTaskFragment != taskFragment) {
final int index = task.mChildren.indexOf(topTaskFragment);
task.mChildren.remove(taskFragment);
task.mChildren.add(index, taskFragment);
}
}
break;
}
}
return effects;
}

View File

@@ -26,6 +26,7 @@ import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT;
import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS;
import static android.window.TaskFragmentOperation.OP_TYPE_SET_ANIMATION_PARAMS;
@@ -1590,6 +1591,46 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
assertEquals(taskFragmentBounds, mTaskFragment.getBounds());
}
@Test
public void testApplyTransaction_reorderTaskFragmentToFront() {
final Task task = createTask(mDisplayContent);
// Create a TaskFragment.
final IBinder token0 = new Binder();
final TaskFragment tf0 = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.setFragmentToken(token0)
.setOrganizer(mOrganizer)
.createActivityCount(1)
.build();
// Create another TaskFragment
final IBinder token1 = new Binder();
final TaskFragment tf1 = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.setFragmentToken(token1)
.setOrganizer(mOrganizer)
.createActivityCount(1)
.build();
// Create a non-embedded Activity on top.
final ActivityRecord topActivity = new ActivityBuilder(mAtm)
.setTask(task)
.build();
mWindowOrganizerController.mLaunchTaskFragments.put(token0, tf0);
mWindowOrganizerController.mLaunchTaskFragments.put(token1, tf1);
// Reorder TaskFragment to front
final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
OP_TYPE_REORDER_TO_FRONT).build();
mTransaction.addTaskFragmentOperation(token0, operation);
assertApplyTransactionAllowed(mTransaction);
// Ensure the non-embedded activity still on top.
assertEquals(topActivity, task.getTopChild().asActivityRecord());
// Ensure the TaskFragment is moved to front.
final TaskFragment frontMostTaskFragment = task.getTaskFragment(tf -> tf.asTask() == null);
assertEquals(frontMostTaskFragment, tf0);
}
/**
* Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls
* {@link WindowOrganizerController#applyTransaction(WindowContainerTransaction)} to apply the