summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java46
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java10
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java12
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java32
-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/SplitControllerTest.java35
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java5
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java9
8 files changed, 97 insertions, 55 deletions
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 82f8a131ae2a..fb3605110d3f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -422,6 +422,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
launchPlaceholderIfNecessary(activity);
}
+ @VisibleForTesting
+ void onActivityDestroyed(@NonNull Activity activity) {
+ // Remove any pending appeared activity, as the server won't send finished activity to the
+ // organizer.
+ for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
+ mTaskContainers.valueAt(i).cleanupPendingAppearedActivity(activity);
+ }
+ // We didn't trigger the callback if there were any pending appeared activities, so check
+ // again after the pending is removed.
+ updateCallbackIfNecessary();
+ }
+
/**
* Called when we have been waiting too long for the TaskFragment to become non-empty after
* creation.
@@ -465,12 +477,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (activityInTask == null) {
throw new IllegalArgumentException("activityInTask must not be null,");
}
- final TaskFragmentContainer container = new TaskFragmentContainer(activity, taskId, this);
if (!mTaskContainers.contains(taskId)) {
mTaskContainers.put(taskId, new TaskContainer(taskId));
}
final TaskContainer taskContainer = mTaskContainers.get(taskId);
- taskContainer.mContainers.add(container);
+ final TaskFragmentContainer container = new TaskFragmentContainer(activity, taskContainer,
+ this);
if (!taskContainer.isTaskBoundsInitialized()) {
// Get the initial bounds before the TaskFragment has appeared.
final Rect taskBounds = SplitPresenter.getTaskBoundsFromActivity(activityInTask);
@@ -500,14 +512,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (splitRule instanceof SplitPairRule && ((SplitPairRule) splitRule).shouldClearTop()) {
removeExistingSecondaryContainers(wct, primaryContainer);
}
- mTaskContainers.get(primaryContainer.getTaskId()).mSplitContainers.add(splitContainer);
+ primaryContainer.getTaskContainer().mSplitContainers.add(splitContainer);
}
/** Cleanups all the dependencies when the TaskFragment is entering PIP. */
private void cleanupForEnterPip(@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer container) {
- final int taskId = container.getTaskId();
- final TaskContainer taskContainer = mTaskContainers.get(taskId);
+ final TaskContainer taskContainer = container.getTaskContainer();
if (taskContainer == null) {
return;
}
@@ -545,8 +556,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
*/
void removeContainer(@NonNull TaskFragmentContainer container) {
// Remove all split containers that included this one
- final int taskId = container.getTaskId();
- final TaskContainer taskContainer = mTaskContainers.get(taskId);
+ final TaskContainer taskContainer = container.getTaskContainer();
if (taskContainer == null) {
return;
}
@@ -637,8 +647,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (splitContainer == null) {
return;
}
- final List<SplitContainer> splitContainers = mTaskContainers.get(container.getTaskId())
- .mSplitContainers;
+ final List<SplitContainer> splitContainers = container.getTaskContainer().mSplitContainers;
if (splitContainer != splitContainers.get(splitContainers.size() - 1)) {
// Skip position update - it isn't the topmost split.
return;
@@ -660,8 +669,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
*/
@Nullable
private SplitContainer getActiveSplitForContainer(@NonNull TaskFragmentContainer container) {
- final List<SplitContainer> splitContainers = mTaskContainers.get(container.getTaskId())
- .mSplitContainers;
+ final List<SplitContainer> splitContainers = container.getTaskContainer().mSplitContainers;
if (splitContainers.isEmpty()) {
return null;
}
@@ -683,11 +691,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
private SplitContainer getActiveSplitForContainers(
@NonNull TaskFragmentContainer firstContainer,
@NonNull TaskFragmentContainer secondContainer) {
- final List<SplitContainer> splitContainers = mTaskContainers.get(firstContainer.getTaskId())
+ final List<SplitContainer> splitContainers = firstContainer.getTaskContainer()
.mSplitContainers;
- if (splitContainers == null) {
- return null;
- }
for (int i = splitContainers.size() - 1; i >= 0; i--) {
final SplitContainer splitContainer = splitContainers.get(i);
final TaskFragmentContainer primary = splitContainer.getPrimaryContainer();
@@ -866,11 +871,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (container == null) {
return false;
}
- final List<SplitContainer> splitContainers = mTaskContainers.get(container.getTaskId())
- .mSplitContainers;
- if (splitContainers == null) {
- return true;
- }
+ final List<SplitContainer> splitContainers = container.getTaskContainer().mSplitContainers;
for (SplitContainer splitContainer : splitContainers) {
if (container.equals(splitContainer.getPrimaryContainer())
|| container.equals(splitContainer.getSecondaryContainer())) {
@@ -1059,6 +1060,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
public void onActivityConfigurationChanged(Activity activity) {
SplitController.this.onActivityConfigurationChanged(activity);
}
+
+ @Override
+ public void onActivityPostDestroyed(Activity activity) {
+ SplitController.this.onActivityDestroyed(activity);
+ }
}
/** Executor that posts on the main application thread. */
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 06c1d4ec8d32..b32f4fa67906 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -291,8 +291,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
// When placeholder is shown in split, we should keep the focus on the primary.
wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
}
- final TaskContainer taskContainer = mController.getTaskContainer(
- updatedContainer.getTaskId());
+ final TaskContainer taskContainer = updatedContainer.getTaskContainer();
final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
primaryRectBounds);
updateTaskFragmentWindowingModeIfRegistered(wct, primaryContainer, windowingMode);
@@ -456,12 +455,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
@NonNull
Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
- final int taskId = container.getTaskId();
- final TaskContainer taskContainer = mController.getTaskContainer(taskId);
- if (taskContainer == null) {
- throw new IllegalStateException("Can't find TaskContainer taskId=" + taskId);
- }
- return taskContainer.getTaskBounds();
+ return container.getTaskContainer().getTaskBounds();
}
@NonNull
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 57628435419e..dba71ef21946 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -16,12 +16,14 @@
package androidx.window.extensions.embedding;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Activity;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.graphics.Rect;
@@ -62,6 +64,9 @@ class TaskContainer {
final Set<IBinder> mFinishedContainer = new ArraySet<>();
TaskContainer(int taskId) {
+ if (taskId == INVALID_TASK_ID) {
+ throw new IllegalArgumentException("Invalid Task id");
+ }
mTaskId = taskId;
}
@@ -130,4 +135,11 @@ class TaskContainer {
boolean isEmpty() {
return mContainers.isEmpty() && mFinishedContainer.isEmpty();
}
+
+ /** Removes the pending appeared activity from all TaskFragments in this Task. */
+ void cleanupPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
+ for (TaskFragmentContainer container : mContainers) {
+ container.removePendingAppearedActivity(pendingAppearedActivity);
+ }
+ }
}
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 35981d3af948..371ec7315a94 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -16,7 +16,6 @@
package androidx.window.extensions.embedding;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.NonNull;
@@ -52,8 +51,9 @@ class TaskFragmentContainer {
@NonNull
private final IBinder mToken;
- /** Parent leaf Task id. */
- private final int mTaskId;
+ /** Parent leaf Task. */
+ @NonNull
+ private final TaskContainer mTaskContainer;
/**
* Server-provided task fragment information.
@@ -100,14 +100,12 @@ class TaskFragmentContainer {
* Creates a container with an existing activity that will be re-parented to it in a window
* container transaction.
*/
- TaskFragmentContainer(@Nullable Activity activity, int taskId,
+ TaskFragmentContainer(@Nullable Activity activity, @NonNull TaskContainer taskContainer,
@NonNull SplitController controller) {
mController = controller;
mToken = new Binder("TaskFragmentContainer");
- if (taskId == INVALID_TASK_ID) {
- throw new IllegalArgumentException("Invalid Task id");
- }
- mTaskId = taskId;
+ mTaskContainer = taskContainer;
+ taskContainer.mContainers.add(this);
if (activity != null) {
addPendingAppearedActivity(activity);
}
@@ -150,9 +148,18 @@ class TaskFragmentContainer {
}
void addPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
+ if (hasActivity(pendingAppearedActivity.getActivityToken())) {
+ return;
+ }
+ // Remove the pending activity from other TaskFragments.
+ mTaskContainer.cleanupPendingAppearedActivity(pendingAppearedActivity);
mPendingAppearedActivities.add(pendingAppearedActivity);
}
+ void removePendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
+ mPendingAppearedActivities.remove(pendingAppearedActivity);
+ }
+
boolean hasActivity(@NonNull IBinder token) {
if (mInfo != null && mInfo.getActivities().contains(token)) {
return true;
@@ -364,7 +371,13 @@ class TaskFragmentContainer {
/** Gets the parent leaf Task id. */
int getTaskId() {
- return mTaskId;
+ return mTaskContainer.getTaskId();
+ }
+
+ /** Gets the parent Task. */
+ @NonNull
+ TaskContainer getTaskContainer() {
+ return mTaskContainer;
}
@Override
@@ -380,6 +393,7 @@ class TaskFragmentContainer {
*/
private String toString(boolean includeContainersToFinishOnExit) {
return "TaskFragmentContainer{"
+ + " parentTaskId=" + getTaskId()
+ " token=" + mToken
+ " topNonFinishingActivity=" + getTopNonFinishingActivity()
+ " runningActivityCount=" + getRunningActivityCount()
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 7aa47ef11cb1..792a53168a0d 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
@@ -113,8 +113,9 @@ public class JetpackTaskFragmentOrganizerTest {
@Test
public void testExpandTaskFragment() {
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- TASK_ID, mSplitController);
+ taskContainer, mSplitController);
final TaskFragmentInfo info = createMockInfo(container);
mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
container.setInfo(info);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 983208c974a1..34cde9bca763 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -22,8 +22,10 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
@@ -35,6 +37,7 @@ import android.app.Activity;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
+import android.os.Binder;
import android.os.Handler;
import android.platform.test.annotations.Presubmit;
import android.window.TaskFragmentInfo;
@@ -96,20 +99,18 @@ public class SplitControllerTest {
@Test
public void testGetTopActiveContainer() {
- TaskContainer taskContainer = new TaskContainer(TASK_ID);
- // tf3 is finished so is not active.
- TaskFragmentContainer tf3 = mock(TaskFragmentContainer.class);
- doReturn(true).when(tf3).isFinished();
- doReturn(false).when(tf3).isWaitingActivityAppear();
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+ // tf1 has no running activity so is not active.
+ final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
+ taskContainer, mSplitController);
// tf2 has running activity so is active.
- TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
+ final TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
doReturn(1).when(tf2).getRunningActivityCount();
- // tf1 has no running activity so is not active.
- TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */, TASK_ID,
- mSplitController);
-
- taskContainer.mContainers.add(tf1);
taskContainer.mContainers.add(tf2);
+ // tf3 is finished so is not active.
+ final TaskFragmentContainer tf3 = mock(TaskFragmentContainer.class);
+ doReturn(true).when(tf3).isFinished();
+ doReturn(false).when(tf3).isWaitingActivityAppear();
taskContainer.mContainers.add(tf3);
mSplitController.mTaskContainers.put(TASK_ID, taskContainer);
@@ -164,6 +165,18 @@ public class SplitControllerTest {
}
@Test
+ public void testOnActivityDestroyed() {
+ doReturn(new Binder()).when(mActivity).getActivityToken();
+ final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
+
+ assertTrue(tf.hasActivity(mActivity.getActivityToken()));
+
+ mSplitController.onActivityDestroyed(mActivity);
+
+ assertFalse(tf.hasActivity(mActivity.getActivityToken()));
+ }
+
+ @Test
public void testNewContainer() {
// Must pass in a valid activity.
assertThrows(IllegalArgumentException.class, () ->
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index c40bab8d9ae3..0de94b0dc26f 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -137,9 +137,8 @@ public class TaskContainerTest {
assertTrue(taskContainer.isEmpty());
- final TaskFragmentContainer tf = new TaskFragmentContainer(null /* activity */, TASK_ID,
- mController);
- taskContainer.mContainers.add(tf);
+ final TaskFragmentContainer tf = new TaskFragmentContainer(null /* activity */,
+ taskContainer, mController);
assertFalse(taskContainer.isEmpty());
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index d80f2b939bf0..ce80cbf323b2 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -76,7 +76,8 @@ public class TaskFragmentContainerTest {
@Test
public void testFinish() {
- final TaskFragmentContainer container = new TaskFragmentContainer(mActivity, TASK_ID,
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+ final TaskFragmentContainer container = new TaskFragmentContainer(mActivity, taskContainer,
mController);
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -107,8 +108,9 @@ public class TaskFragmentContainerTest {
@Test
public void testIsWaitingActivityAppear() {
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- TASK_ID, mController);
+ taskContainer, mController);
assertTrue(container.isWaitingActivityAppear());
@@ -127,8 +129,9 @@ public class TaskFragmentContainerTest {
@Test
public void testAppearEmptyTimeout() {
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
- TASK_ID, mController);
+ taskContainer, mController);
assertNull(container.mAppearEmptyTimeout);