Loading core/java/android/window/TaskFragmentParentInfo.java +20 −3 Original line number Diff line number Diff line Loading @@ -35,17 +35,21 @@ public class TaskFragmentParentInfo implements Parcelable { private final boolean mVisible; private final boolean mHasDirectActivity; public TaskFragmentParentInfo(@NonNull Configuration configuration, int displayId, boolean visible) { boolean visible, boolean hasDirectActivity) { mConfiguration.setTo(configuration); mDisplayId = displayId; mVisible = visible; mHasDirectActivity = hasDirectActivity; } public TaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.mDisplayId; mVisible = info.mVisible; mHasDirectActivity = info.mHasDirectActivity; } /** The {@link Configuration} of the parent Task */ Loading @@ -67,6 +71,14 @@ public class TaskFragmentParentInfo implements Parcelable { return mVisible; } /** * Whether the parent Task has any direct child activity, which is not embedded in any * TaskFragment, or not */ public boolean hasDirectActivity() { return mHasDirectActivity; } /** * Returns {@code true} if the parameters which are important for task fragment * organizers are equal between this {@link TaskFragmentParentInfo} and {@code that}. Loading @@ -80,7 +92,7 @@ public class TaskFragmentParentInfo implements Parcelable { return false; } return getWindowingMode() == that.getWindowingMode() && mDisplayId == that.mDisplayId && mVisible == that.mVisible; && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity; } @WindowConfiguration.WindowingMode Loading @@ -94,6 +106,7 @@ public class TaskFragmentParentInfo implements Parcelable { + "config=" + mConfiguration + ", displayId=" + mDisplayId + ", visible=" + mVisible + ", hasDirectActivity=" + mHasDirectActivity + "}"; } Loading @@ -114,7 +127,8 @@ public class TaskFragmentParentInfo implements Parcelable { final TaskFragmentParentInfo that = (TaskFragmentParentInfo) obj; return mConfiguration.equals(that.mConfiguration) && mDisplayId == that.mDisplayId && mVisible == that.mVisible; && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity; } @Override Loading @@ -122,6 +136,7 @@ public class TaskFragmentParentInfo implements Parcelable { int result = mConfiguration.hashCode(); result = 31 * result + mDisplayId; result = 31 * result + (mVisible ? 1 : 0); result = 31 * result + (mHasDirectActivity ? 1 : 0); return result; } Loading @@ -130,12 +145,14 @@ public class TaskFragmentParentInfo implements Parcelable { mConfiguration.writeToParcel(dest, flags); dest.writeInt(mDisplayId); dest.writeBoolean(mVisible); dest.writeBoolean(mHasDirectActivity); } private TaskFragmentParentInfo(Parcel in) { mConfiguration.readFromParcel(in); mDisplayId = in.readInt(); mVisible = in.readBoolean(); mHasDirectActivity = in.readBoolean(); } public static final Creator<TaskFragmentParentInfo> CREATOR = Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +28 −0 Original line number Diff line number Diff line Loading @@ -1763,6 +1763,15 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } if (container.isFinished()) { return; } if (container.isOverlay()) { updateOverlayContainer(wct, container); return; } if (launchPlaceholderIfNecessary(wct, container)) { // Placeholder was launched, the positions will be updated when the activity is added // to the secondary container. Loading @@ -1783,6 +1792,25 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen updateSplitContainerIfNeeded(splitContainer, wct, null /* splitAttributes */); } @VisibleForTesting // Suppress GuardedBy warning because lint ask to mark this method as // @GuardedBy(mPresenter.mController.mLock), which is mLock itself @SuppressWarnings("GuardedBy") @GuardedBy("mLock") void updateOverlayContainer(@NonNull WindowContainerTransaction wct, @NonNull TaskFragmentContainer container) { final TaskContainer taskContainer = container.getTaskContainer(); // Dismiss the overlay container if it's the only container in the task and there's no // direct activity in the parent task. if (taskContainer.getTaskFragmentContainers().size() == 1 && !taskContainer.hasDirectActivity()) { container.finish(false /* shouldFinishDependent */, mPresenter, wct, this); } // TODO(b/295805054): Add the logic to update overlay container } /** * Updates {@link SplitContainer} with the given {@link SplitAttributes} if the * {@link SplitContainer} is the top most and not finished. If passed {@link SplitAttributes} Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +9 −1 Original line number Diff line number Diff line Loading @@ -75,6 +75,8 @@ class TaskContainer { private boolean mIsVisible; private boolean mHasDirectActivity; /** * TaskFragments that the organizer has requested to be closed. They should be removed when * the organizer receives Loading Loading @@ -102,8 +104,9 @@ class TaskContainer { mConfiguration = taskProperties.getConfiguration(); mDisplayId = taskProperties.getDisplayId(); // Note that it is always called when there's a new Activity is started, which implies // the host task is visible. // the host task is visible and has an activity in the task. mIsVisible = true; mHasDirectActivity = true; } int getTaskId() { Loading @@ -118,6 +121,10 @@ class TaskContainer { return mIsVisible; } boolean hasDirectActivity() { return mHasDirectActivity; } @NonNull TaskProperties getTaskProperties() { return new TaskProperties(mDisplayId, mConfiguration); Loading @@ -127,6 +134,7 @@ class TaskContainer { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.getDisplayId(); mIsVisible = info.isVisible(); mHasDirectActivity = info.hasDirectActivity(); } /** Loading libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java +28 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.window.TaskFragmentInfo; import android.window.TaskFragmentParentInfo; import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; Loading Loading @@ -413,6 +414,33 @@ public class OverlayPresentationTest { .isEqualTo(overlayContainer); } @Test public void testUpdateContainer_dontInvokeUpdateOverlayForNonOverlayContainer() { TaskFragmentContainer taskFragmentContainer = createMockTaskFragmentContainer(mActivity); mSplitController.updateContainer(mTransaction, taskFragmentContainer); verify(mSplitController, never()).updateOverlayContainer(any(), any()); } @Test public void testUpdateOverlayContainer_dismissOverlayIfNeeded() { TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test"); mSplitController.updateOverlayContainer(mTransaction, overlayContainer); final TaskContainer taskContainer = overlayContainer.getTaskContainer(); assertThat(taskContainer.getTaskFragmentContainers()).containsExactly(overlayContainer); taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(Configuration.EMPTY, DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */)); mSplitController.updateOverlayContainer(mTransaction, overlayContainer); assertWithMessage("The overlay must be dismissed since there's no activity" + " in the task and other taskFragment.") .that(taskContainer.getTaskFragmentContainers()).isEmpty(); } /** * A simplified version of {@link SplitController.ActivityStartMonitor * #createOrUpdateOverlayTaskFragmentIfNeeded} Loading libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -1139,7 +1139,7 @@ public class SplitControllerTest { public void testOnTransactionReady_taskFragmentParentInfoChanged() { final TaskFragmentTransaction transaction = new TaskFragmentTransaction(); final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(Configuration.EMPTY, DEFAULT_DISPLAY, true); DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */); transaction.addChange(new TaskFragmentTransaction.Change( TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED) .setTaskId(TASK_ID) Loading Loading
core/java/android/window/TaskFragmentParentInfo.java +20 −3 Original line number Diff line number Diff line Loading @@ -35,17 +35,21 @@ public class TaskFragmentParentInfo implements Parcelable { private final boolean mVisible; private final boolean mHasDirectActivity; public TaskFragmentParentInfo(@NonNull Configuration configuration, int displayId, boolean visible) { boolean visible, boolean hasDirectActivity) { mConfiguration.setTo(configuration); mDisplayId = displayId; mVisible = visible; mHasDirectActivity = hasDirectActivity; } public TaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.mDisplayId; mVisible = info.mVisible; mHasDirectActivity = info.mHasDirectActivity; } /** The {@link Configuration} of the parent Task */ Loading @@ -67,6 +71,14 @@ public class TaskFragmentParentInfo implements Parcelable { return mVisible; } /** * Whether the parent Task has any direct child activity, which is not embedded in any * TaskFragment, or not */ public boolean hasDirectActivity() { return mHasDirectActivity; } /** * Returns {@code true} if the parameters which are important for task fragment * organizers are equal between this {@link TaskFragmentParentInfo} and {@code that}. Loading @@ -80,7 +92,7 @@ public class TaskFragmentParentInfo implements Parcelable { return false; } return getWindowingMode() == that.getWindowingMode() && mDisplayId == that.mDisplayId && mVisible == that.mVisible; && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity; } @WindowConfiguration.WindowingMode Loading @@ -94,6 +106,7 @@ public class TaskFragmentParentInfo implements Parcelable { + "config=" + mConfiguration + ", displayId=" + mDisplayId + ", visible=" + mVisible + ", hasDirectActivity=" + mHasDirectActivity + "}"; } Loading @@ -114,7 +127,8 @@ public class TaskFragmentParentInfo implements Parcelable { final TaskFragmentParentInfo that = (TaskFragmentParentInfo) obj; return mConfiguration.equals(that.mConfiguration) && mDisplayId == that.mDisplayId && mVisible == that.mVisible; && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity; } @Override Loading @@ -122,6 +136,7 @@ public class TaskFragmentParentInfo implements Parcelable { int result = mConfiguration.hashCode(); result = 31 * result + mDisplayId; result = 31 * result + (mVisible ? 1 : 0); result = 31 * result + (mHasDirectActivity ? 1 : 0); return result; } Loading @@ -130,12 +145,14 @@ public class TaskFragmentParentInfo implements Parcelable { mConfiguration.writeToParcel(dest, flags); dest.writeInt(mDisplayId); dest.writeBoolean(mVisible); dest.writeBoolean(mHasDirectActivity); } private TaskFragmentParentInfo(Parcel in) { mConfiguration.readFromParcel(in); mDisplayId = in.readInt(); mVisible = in.readBoolean(); mHasDirectActivity = in.readBoolean(); } public static final Creator<TaskFragmentParentInfo> CREATOR = Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +28 −0 Original line number Diff line number Diff line Loading @@ -1763,6 +1763,15 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } if (container.isFinished()) { return; } if (container.isOverlay()) { updateOverlayContainer(wct, container); return; } if (launchPlaceholderIfNecessary(wct, container)) { // Placeholder was launched, the positions will be updated when the activity is added // to the secondary container. Loading @@ -1783,6 +1792,25 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen updateSplitContainerIfNeeded(splitContainer, wct, null /* splitAttributes */); } @VisibleForTesting // Suppress GuardedBy warning because lint ask to mark this method as // @GuardedBy(mPresenter.mController.mLock), which is mLock itself @SuppressWarnings("GuardedBy") @GuardedBy("mLock") void updateOverlayContainer(@NonNull WindowContainerTransaction wct, @NonNull TaskFragmentContainer container) { final TaskContainer taskContainer = container.getTaskContainer(); // Dismiss the overlay container if it's the only container in the task and there's no // direct activity in the parent task. if (taskContainer.getTaskFragmentContainers().size() == 1 && !taskContainer.hasDirectActivity()) { container.finish(false /* shouldFinishDependent */, mPresenter, wct, this); } // TODO(b/295805054): Add the logic to update overlay container } /** * Updates {@link SplitContainer} with the given {@link SplitAttributes} if the * {@link SplitContainer} is the top most and not finished. If passed {@link SplitAttributes} Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +9 −1 Original line number Diff line number Diff line Loading @@ -75,6 +75,8 @@ class TaskContainer { private boolean mIsVisible; private boolean mHasDirectActivity; /** * TaskFragments that the organizer has requested to be closed. They should be removed when * the organizer receives Loading Loading @@ -102,8 +104,9 @@ class TaskContainer { mConfiguration = taskProperties.getConfiguration(); mDisplayId = taskProperties.getDisplayId(); // Note that it is always called when there's a new Activity is started, which implies // the host task is visible. // the host task is visible and has an activity in the task. mIsVisible = true; mHasDirectActivity = true; } int getTaskId() { Loading @@ -118,6 +121,10 @@ class TaskContainer { return mIsVisible; } boolean hasDirectActivity() { return mHasDirectActivity; } @NonNull TaskProperties getTaskProperties() { return new TaskProperties(mDisplayId, mConfiguration); Loading @@ -127,6 +134,7 @@ class TaskContainer { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.getDisplayId(); mIsVisible = info.isVisible(); mHasDirectActivity = info.hasDirectActivity(); } /** Loading
libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java +28 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.window.TaskFragmentInfo; import android.window.TaskFragmentParentInfo; import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; Loading Loading @@ -413,6 +414,33 @@ public class OverlayPresentationTest { .isEqualTo(overlayContainer); } @Test public void testUpdateContainer_dontInvokeUpdateOverlayForNonOverlayContainer() { TaskFragmentContainer taskFragmentContainer = createMockTaskFragmentContainer(mActivity); mSplitController.updateContainer(mTransaction, taskFragmentContainer); verify(mSplitController, never()).updateOverlayContainer(any(), any()); } @Test public void testUpdateOverlayContainer_dismissOverlayIfNeeded() { TaskFragmentContainer overlayContainer = createTestOverlayContainer(TASK_ID, "test"); mSplitController.updateOverlayContainer(mTransaction, overlayContainer); final TaskContainer taskContainer = overlayContainer.getTaskContainer(); assertThat(taskContainer.getTaskFragmentContainers()).containsExactly(overlayContainer); taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(Configuration.EMPTY, DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */)); mSplitController.updateOverlayContainer(mTransaction, overlayContainer); assertWithMessage("The overlay must be dismissed since there's no activity" + " in the task and other taskFragment.") .that(taskContainer.getTaskFragmentContainers()).isEmpty(); } /** * A simplified version of {@link SplitController.ActivityStartMonitor * #createOrUpdateOverlayTaskFragmentIfNeeded} Loading
libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -1139,7 +1139,7 @@ public class SplitControllerTest { public void testOnTransactionReady_taskFragmentParentInfoChanged() { final TaskFragmentTransaction transaction = new TaskFragmentTransaction(); final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(Configuration.EMPTY, DEFAULT_DISPLAY, true); DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */); transaction.addChange(new TaskFragmentTransaction.Change( TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED) .setTaskId(TASK_ID) Loading