summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/window/TaskFragmentInfo.java21
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java4
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java7
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java24
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java3
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java27
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java16
7 files changed, 81 insertions, 21 deletions
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index fa5195727afe..23a1224fcc4e 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -102,6 +102,8 @@ public final class TaskFragmentInfo implements Parcelable {
@NonNull
private final Point mMinimumDimensions = new Point();
+ private final boolean mIsTopNonFishingChild;
+
/** @hide */
public TaskFragmentInfo(
@NonNull IBinder fragmentToken, @NonNull WindowContainerToken token,
@@ -110,7 +112,7 @@ public final class TaskFragmentInfo implements Parcelable {
@NonNull List<IBinder> inRequestedTaskFragmentActivities,
@NonNull Point positionInParent, boolean isTaskClearedForReuse,
boolean isTaskFragmentClearedForPip, boolean isClearedForReorderActivityToFront,
- @NonNull Point minimumDimensions) {
+ @NonNull Point minimumDimensions, boolean isTopNonFinishingChild) {
mFragmentToken = requireNonNull(fragmentToken);
mToken = requireNonNull(token);
mConfiguration.setTo(configuration);
@@ -123,6 +125,7 @@ public final class TaskFragmentInfo implements Parcelable {
mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
mIsClearedForReorderActivityToFront = isClearedForReorderActivityToFront;
mMinimumDimensions.set(minimumDimensions);
+ mIsTopNonFishingChild = isTopNonFinishingChild;
}
@NonNull
@@ -212,6 +215,16 @@ public final class TaskFragmentInfo implements Parcelable {
}
/**
+ * Indicates that this TaskFragment is the top non-finishing child of its parent container
+ * among all Activities and TaskFragment siblings.
+ *
+ * @hide
+ */
+ public boolean isTopNonFinishingChild() {
+ return mIsTopNonFishingChild;
+ }
+
+ /**
* Returns {@code true} if the parameters that are important for task fragment organizers are
* equal between this {@link TaskFragmentInfo} and {@param that}.
* Note that this method is usually called with
@@ -236,7 +249,8 @@ public final class TaskFragmentInfo implements Parcelable {
&& mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
&& mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
&& mIsClearedForReorderActivityToFront == that.mIsClearedForReorderActivityToFront
- && mMinimumDimensions.equals(that.mMinimumDimensions);
+ && mMinimumDimensions.equals(that.mMinimumDimensions)
+ && mIsTopNonFishingChild == that.mIsTopNonFishingChild;
}
private TaskFragmentInfo(Parcel in) {
@@ -252,6 +266,7 @@ public final class TaskFragmentInfo implements Parcelable {
mIsTaskFragmentClearedForPip = in.readBoolean();
mIsClearedForReorderActivityToFront = in.readBoolean();
mMinimumDimensions.readFromParcel(in);
+ mIsTopNonFishingChild = in.readBoolean();
}
/** @hide */
@@ -269,6 +284,7 @@ public final class TaskFragmentInfo implements Parcelable {
dest.writeBoolean(mIsTaskFragmentClearedForPip);
dest.writeBoolean(mIsClearedForReorderActivityToFront);
mMinimumDimensions.writeToParcel(dest, flags);
+ dest.writeBoolean(mIsTopNonFishingChild);
}
@NonNull
@@ -299,6 +315,7 @@ public final class TaskFragmentInfo implements Parcelable {
+ " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip
+ " mIsClearedForReorderActivityToFront=" + mIsClearedForReorderActivityToFront
+ " minimumDimensions=" + mMinimumDimensions
+ + " isTopNonFinishingChild=" + mIsTopNonFishingChild
+ "}";
}
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 e71d844ade59..409cde30cf8c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -2759,9 +2759,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// in the same task, the overlay will be dismissed in case an activity above
// the overlay is dismissed and the overlay is shown unexpectedly.
for (final TaskFragmentContainer overlayContainer : overlayContainers) {
- final boolean isTopNonFinishingOverlay = overlayContainer.equals(
- overlayContainer.getTaskContainer().getTopNonFinishingTaskFragmentContainer(
- true /* includePin */, true /* includeOverlay */));
+ final boolean isTopNonFinishingOverlay = overlayContainer.isTopNonFinishingChild();
final boolean areInSameTask = taskId == overlayContainer.getTaskId();
final boolean haveSameTag = overlayTag.equals(overlayContainer.getOverlayTag());
if (!associateLaunchingActivity && overlayContainer.isAlwaysOnTopOverlay()
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 7173b0c95230..d0e2c998e961 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -340,6 +340,13 @@ class TaskFragmentContainer {
return mInfo != null && mInfo.isVisible();
}
+ /**
+ * See {@link TaskFragmentInfo#isTopNonFinishingChild()}
+ */
+ boolean isTopNonFinishingChild() {
+ return mInfo != null && mInfo.isTopNonFinishingChild();
+ }
+
/** Whether the TaskFragment is in an intermediate state waiting for the server update.*/
boolean isInIntermediateState() {
if (mInfo == null) {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
index d649c6d57137..7dc78fdd601f 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -163,12 +163,14 @@ public class EmbeddingTestUtils {
}
/** Creates a mock TaskFragmentInfo for the given TaskFragment. */
+ @NonNull
static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
@NonNull Activity activity) {
return createMockTaskFragmentInfo(container, activity, true /* isVisible */);
}
/** Creates a mock TaskFragmentInfo for the given TaskFragment. */
+ @NonNull
static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
@NonNull Activity activity, boolean isVisible) {
return new TaskFragmentInfo(container.getTaskFragmentToken(),
@@ -182,7 +184,27 @@ public class EmbeddingTestUtils {
false /* isTaskClearedForReuse */,
false /* isTaskFragmentClearedForPip */,
false /* isClearedForReorderActivityToFront */,
- new Point());
+ new Point(),
+ false /* isTopChild */);
+ }
+
+ /** Creates a mock TaskFragmentInfo for the given TaskFragment. */
+ @NonNull
+ static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
+ @NonNull Activity activity, boolean isVisible, boolean isOnTop) {
+ return new TaskFragmentInfo(container.getTaskFragmentToken(),
+ mock(WindowContainerToken.class),
+ new Configuration(),
+ 1,
+ isVisible,
+ Collections.singletonList(activity.getActivityToken()),
+ new ArrayList<>(),
+ new Point(),
+ false /* isTaskClearedForReuse */,
+ false /* isTaskFragmentClearedForPip */,
+ false /* isClearedForReorderActivityToFront */,
+ new Point(),
+ isOnTop);
}
static ActivityInfo createActivityInfoWithMinDimensions() {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index ad41b18dcbc6..8911d18b9b97 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -114,6 +114,7 @@ public class JetpackTaskFragmentOrganizerTest {
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
false /* isVisible */, new ArrayList<>(), new ArrayList<>(), new Point(),
false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
- false /* isClearedForReorderActivityToFront */, new Point());
+ false /* isClearedForReorderActivityToFront */, new Point(),
+ false /* isTopChild */);
}
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index f799bf9a1052..475475b05272 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -269,7 +269,7 @@ public class OverlayPresentationTest {
}
@Test
- public void testCreateOrUpdateOverlay_visibleOverlayInTask_dismissOverlay() {
+ public void testCreateOrUpdateOverlay_topOverlayInTask_dismissOverlay() {
createExistingOverlayContainers();
final TaskFragmentContainer overlayContainer =
@@ -400,13 +400,13 @@ public class OverlayPresentationTest {
}
private void createExistingOverlayContainers() {
- createExistingOverlayContainers(true /* visible */);
+ createExistingOverlayContainers(true /* isOnTop */);
}
- private void createExistingOverlayContainers(boolean visible) {
- mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", visible,
+ private void createExistingOverlayContainers(boolean isOnTop) {
+ mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", isOnTop,
true /* associatedLaunchingActivity */, mActivity);
- mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2", visible);
+ mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2", isOnTop);
List<TaskFragmentContainer> overlayContainers = mSplitController
.getAllNonFinishingOverlayContainers();
assertThat(overlayContainers).containsExactly(mOverlayContainer1, mOverlayContainer2);
@@ -1004,10 +1004,10 @@ public class OverlayPresentationTest {
/** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
@NonNull
private TaskFragmentContainer createMockTaskFragmentContainer(
- @NonNull Activity activity, boolean isVisible) {
+ @NonNull Activity activity, boolean isOnTop) {
final TaskFragmentContainer container = createTfContainer(mSplitController,
activity.getTaskId(), activity);
- setupTaskFragmentInfo(container, activity, isVisible);
+ setupTaskFragmentInfo(container, activity, isOnTop);
return container;
}
@@ -1019,8 +1019,8 @@ public class OverlayPresentationTest {
@NonNull
private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
- boolean isVisible) {
- return createTestOverlayContainer(taskId, tag, isVisible,
+ boolean isOnTop) {
+ return createTestOverlayContainer(taskId, tag, isOnTop,
true /* associateLaunchingActivity */);
}
@@ -1033,7 +1033,7 @@ public class OverlayPresentationTest {
@NonNull
private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
- boolean isVisible, boolean associateLaunchingActivity,
+ boolean isOnTop, boolean associateLaunchingActivity,
@Nullable Activity launchingActivity) {
final Activity activity = launchingActivity != null
? launchingActivity : createMockActivity();
@@ -1044,14 +1044,15 @@ public class OverlayPresentationTest {
.setLaunchOptions(Bundle.EMPTY)
.setAssociatedActivity(associateLaunchingActivity ? activity : null)
.build();
- setupTaskFragmentInfo(overlayContainer, createMockActivity(), isVisible);
+ setupTaskFragmentInfo(overlayContainer, createMockActivity(), isOnTop);
return overlayContainer;
}
private void setupTaskFragmentInfo(@NonNull TaskFragmentContainer container,
@NonNull Activity activity,
- boolean isVisible) {
- final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity, isVisible);
+ boolean isOnTop) {
+ final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity, isOnTop,
+ isOnTop);
container.setInfo(mTransaction, info);
mSplitPresenter.mFragmentInfos.put(container.getTaskFragmentToken(), info);
}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index c83b28055a2f..ed0dc3be9465 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2819,7 +2819,21 @@ class TaskFragment extends WindowContainer<WindowContainer> {
mClearedTaskForReuse,
mClearedTaskFragmentForPip,
mClearedForReorderActivityToFront,
- calculateMinDimension());
+ calculateMinDimension(),
+ isTopNonFinishingChild());
+ }
+
+ private boolean isTopNonFinishingChild() {
+ final WindowContainer<?> parent = getParent();
+ if (parent == null) {
+ // Either the TaskFragment is not attached or is going to destroy. Return false.
+ return false;
+ }
+ final ActivityRecord topNonFishingActivity = parent.getActivity(ar -> !ar.finishing);
+ // If the parent's top non-finishing activity is this TaskFragment's, it means
+ // this TaskFragment is the top non-finishing container of its parent.
+ return topNonFishingActivity != null && topNonFishingActivity
+ .equals(getTopNonFinishingActivity());
}
/**