diff options
| author | 2023-04-19 06:42:59 +0000 | |
|---|---|---|
| committer | 2023-07-07 04:12:16 +0000 | |
| commit | 55d276a227a29022a33c3a8f71966075d8897d11 (patch) | |
| tree | 270ad6019000d81be58ff966ed1dfdfadd335c12 | |
| parent | 4944e8e0717dfaa5d85b31bd93353d80d7f287f2 (diff) | |
[4/n] Pin ActivityStack
Keeps the pinned TaskFragment on the front in WM hierarchy when needed.
Do not launch placeholder or make it always-expand if the container
is pinned.
Bug: 208573140
Test: TaskFragmentOrganizerControllerTest
Change-Id: I22e258ef039e3128f56078bb77d6a637fb545942
6 files changed, 85 insertions, 5 deletions
diff --git a/core/java/android/window/TaskFragmentOperation.java b/core/java/android/window/TaskFragmentOperation.java index 413f0ccbc275..e153bb70a7ca 100644 --- a/core/java/android/window/TaskFragmentOperation.java +++ b/core/java/android/window/TaskFragmentOperation.java @@ -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 {} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index 47bd6adb11e2..a2f75e099465 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -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; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index 6630e05a8b0a..4dafbd17f379 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -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 diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java index 822adbd84454..969e3ed5b9b6 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java @@ -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); } diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 31918f478e44..7017e6b1111d 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -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; @@ -1333,6 +1334,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; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index 99ab715ab987..54b935132957 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -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 |