From fd76c2da5fd1d0f0c7a4c79bb8474fe776e57ec8 Mon Sep 17 00:00:00 2001 From: Jiaming Liu Date: Fri, 19 Jan 2024 22:26:50 +0000 Subject: Add TF flag to allow transitions when empty By default, the TaskFragment waits until it becomes non-empty to start transitions. If mAllowTransitionWhenEmpty is set to true, then it will start transition even if it is empty. This is need for Launcher to create an empty TF and obtain the surface before launching the -1 activity. Bug: 320720349 Test: atest TaskFragmentTest Change-Id: Ie7aca6391032e660dd2bc243ddba53db945af09f --- .../android/window/TaskFragmentCreationParams.java | 36 ++++++++++++++++++++-- .../java/com/android/server/wm/TaskFragment.java | 27 ++++++++++++++-- .../server/wm/WindowOrganizerController.java | 1 + .../com/android/server/wm/TaskFragmentTest.java | 4 +++ 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/core/java/android/window/TaskFragmentCreationParams.java b/core/java/android/window/TaskFragmentCreationParams.java index 5dbf328b6c0a..93297e64c621 100644 --- a/core/java/android/window/TaskFragmentCreationParams.java +++ b/core/java/android/window/TaskFragmentCreationParams.java @@ -94,11 +94,18 @@ public final class TaskFragmentCreationParams implements Parcelable { @Nullable private final IBinder mPairedActivityToken; + /** + * If {@code true}, transitions are allowed even if the TaskFragment is empty. If + * {@code false}, transitions will wait until the TaskFragment becomes non-empty or other + * conditions are met. Default to {@code false}. + */ + private final boolean mAllowTransitionWhenEmpty; + private TaskFragmentCreationParams( @NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds, @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken, - @Nullable IBinder pairedActivityToken) { + @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty) { if (pairedPrimaryFragmentToken != null && pairedActivityToken != null) { throw new IllegalArgumentException("pairedPrimaryFragmentToken and" + " pairedActivityToken should not be set at the same time."); @@ -110,6 +117,7 @@ public final class TaskFragmentCreationParams implements Parcelable { mWindowingMode = windowingMode; mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken; mPairedActivityToken = pairedActivityToken; + mAllowTransitionWhenEmpty = allowTransitionWhenEmpty; } @NonNull @@ -155,6 +163,11 @@ public final class TaskFragmentCreationParams implements Parcelable { return mPairedActivityToken; } + /** @hide */ + public boolean getAllowTransitionWhenEmpty() { + return mAllowTransitionWhenEmpty; + } + private TaskFragmentCreationParams(Parcel in) { mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in); mFragmentToken = in.readStrongBinder(); @@ -163,6 +176,7 @@ public final class TaskFragmentCreationParams implements Parcelable { mWindowingMode = in.readInt(); mPairedPrimaryFragmentToken = in.readStrongBinder(); mPairedActivityToken = in.readStrongBinder(); + mAllowTransitionWhenEmpty = in.readBoolean(); } /** @hide */ @@ -175,6 +189,7 @@ public final class TaskFragmentCreationParams implements Parcelable { dest.writeInt(mWindowingMode); dest.writeStrongBinder(mPairedPrimaryFragmentToken); dest.writeStrongBinder(mPairedActivityToken); + dest.writeBoolean(mAllowTransitionWhenEmpty); } @NonNull @@ -201,6 +216,7 @@ public final class TaskFragmentCreationParams implements Parcelable { + " windowingMode=" + mWindowingMode + " pairedFragmentToken=" + mPairedPrimaryFragmentToken + " pairedActivityToken=" + mPairedActivityToken + + " allowTransitionWhenEmpty=" + mAllowTransitionWhenEmpty + "}"; } @@ -234,6 +250,8 @@ public final class TaskFragmentCreationParams implements Parcelable { @Nullable private IBinder mPairedActivityToken; + private boolean mAllowTransitionWhenEmpty; + public Builder(@NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) { mOrganizer = organizer; @@ -298,12 +316,26 @@ public final class TaskFragmentCreationParams implements Parcelable { return this; } + /** + * Sets whether transitions are allowed when the TaskFragment is empty. If {@code true}, + * transitions are allowed when the TaskFragment is empty. If {@code false}, transitions + * will wait until the TaskFragment becomes non-empty or other conditions are met. Default + * to {@code false}. + * + * @hide + */ + @NonNull + public Builder setAllowTransitionWhenEmpty(boolean allowTransitionWhenEmpty) { + mAllowTransitionWhenEmpty = allowTransitionWhenEmpty; + return this; + } + /** Constructs the options to create TaskFragment with. */ @NonNull public TaskFragmentCreationParams build() { return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken, mInitialRelativeBounds, mWindowingMode, mPairedPrimaryFragmentToken, - mPairedActivityToken); + mPairedActivityToken, mAllowTransitionWhenEmpty); } } } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 7d418eae6548..3980cae0ba99 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -369,6 +369,15 @@ class TaskFragment extends WindowContainer { */ private boolean mMoveToBottomIfClearWhenLaunch; + /** + * If {@code true}, transitions are allowed even if this TaskFragment is empty. If + * {@code false}, transitions will wait until this TaskFragment becomes non-empty or other + * conditions are met. Default to {@code false}. + * + * @see #isReadyToTransit + */ + private boolean mAllowTransitionWhenEmpty; + /** When set, will force the task to report as invisible. */ static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1; static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; @@ -509,6 +518,19 @@ class TaskFragment extends WindowContainer { mIsolatedNav = isolatedNav; } + /** + * Sets whether transitions are allowed when the TaskFragment is empty. If {@code true}, + * transitions are allowed when the TaskFragment is empty. If {@code false}, transitions + * will wait until the TaskFragment becomes non-empty or other conditions are met. Default + * to {@code false}. + */ + void setAllowTransitionWhenEmpty(boolean allowTransitionWhenEmpty) { + if (!isEmbedded()) { + return; + } + mAllowTransitionWhenEmpty = allowTransitionWhenEmpty; + } + /** @see #mIsolatedNav */ boolean isIsolatedNav() { return isEmbedded() && mIsolatedNav; @@ -2814,8 +2836,9 @@ class TaskFragment extends WindowContainer { return true; } // We don't want to start the transition if the organized TaskFragment is empty, unless - // it is requested to be removed. - if (getTopNonFinishingActivity() != null || mIsRemovalRequested) { + // it is requested to be removed or the mAllowTransitionWhenEmpty flag is true. + if (getTopNonFinishingActivity() != null || mIsRemovalRequested + || mAllowTransitionWhenEmpty) { return true; } // Organizer shouldn't change embedded TaskFragment in PiP. diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 205ed977f316..4ba52e4c0fd7 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -2202,6 +2202,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } final TaskFragment taskFragment = new TaskFragment(mService, creationParams.getFragmentToken(), true /* createdByOrganizer */); + taskFragment.setAllowTransitionWhenEmpty(creationParams.getAllowTransitionWhenEmpty()); // Set task fragment organizer immediately, since it might have to be notified about further // actions. TaskFragmentOrganizerToken organizerToken = creationParams.getOrganizer(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index 22ddf8420121..3f103483a6d7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -436,6 +436,10 @@ public class TaskFragmentTest extends WindowTestsBase { // Not ready if the task is still visible when the TaskFragment becomes empty. doReturn(true).when(task).isVisibleRequested(); assertFalse(taskFragment.isReadyToTransit()); + + // Ready if the mAllowTransitionWhenEmpty flag is true. + taskFragment.setAllowTransitionWhenEmpty(true); + assertTrue(taskFragment.isReadyToTransit()); } @Test -- cgit v1.2.3-59-g8ed1b