Finish non-standard activity type when display removed
- Always finish non-standard activity type when a display is
removed.
- Don't release activity display related resources until all
activities within the display are destroyed.
- For most cases, let stack inherited the windowing mode
from the new display after reparent.
Bug: 111363427
Test: atest ActivityManagerMultiDisplayTests
atest FrameworksServicesTests:com.android.server.am.ActivityStackTests
Change-Id: I2bc57a84e191abe1ac5b5b1bb6951e76a2d5bc22
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 73ffd5c..3568a47 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -31,6 +31,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
+
import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID;
import static com.android.server.am.ActivityDisplayProto.ID;
@@ -43,7 +44,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStackSupervisor.TAG_STATES;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
@@ -103,6 +103,12 @@
private boolean mSleeping;
+ /**
+ * The display is removed from the system and we are just waiting for all activities on it to be
+ * finished before removing this object.
+ */
+ private boolean mRemoved;
+
// Cached reference to some special stacks we tend to get a lot so we don't need to loop
// through the list to find them.
private ActivityStack mHomeStack = null;
@@ -155,6 +161,7 @@
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
removeStackReferenceIfNeeded(stack);
+ releaseSelfIfNeeded();
mSupervisor.mService.updateSleepIfNeededLocked();
onStackOrderChanged();
}
@@ -484,16 +491,11 @@
final int windowingMode = stack.getWindowingMode();
if (activityType == ACTIVITY_TYPE_HOME) {
- // TODO(b/111363427) Rollback to throws exceptions once we figure out how to properly
- // deal with home type stack when external display removed
if (mHomeStack != null && mHomeStack != stack) {
- // throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
- // + mHomeStack + " already exist on display=" + this + " stack=" + stack);
- Slog.e(TAG, "addStackReferenceIfNeeded: home stack="
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+ mHomeStack + " already exist on display=" + this + " stack=" + stack);
- } else {
- mHomeStack = stack;
}
+ mHomeStack = stack;
} else if (activityType == ACTIVITY_TYPE_RECENTS) {
if (mRecentsStack != null && mRecentsStack != stack) {
throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
@@ -796,28 +798,47 @@
return false;
}
+ /**
+ * @see #mRemoved
+ */
+ boolean isRemoved() {
+ return mRemoved;
+ }
+
void remove() {
final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
- while (getChildCount() > 0) {
- final ActivityStack stack = getChildAt(0);
- if (destroyContentOnRemoval) {
- // Override the stack configuration to make it equal to the current applied one, so
- // that we don't accidentally report configuration change to activities that are
- // going to be finished.
- stack.onOverrideConfigurationChanged(stack.getConfiguration());
- mSupervisor.moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY,
- false /* onTop */);
+
+ // Stacks could be reparented from the removed display to other display. While
+ // reparenting the last stack of the removed display, the remove display is ready to be
+ // released (no more ActivityStack). But, we cannot release it at that moment or the
+ // related WindowContainer and WindowContainerController will also be removed. So, we
+ // set display as removed after reparenting stack finished.
+ for (int i = mStacks.size() - 1; i >= 0; --i) {
+ final ActivityStack stack = mStacks.get(i);
+ // Always finish non-standard type stacks.
+ if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
stack.finishAllActivitiesLocked(true /* immediately */);
} else {
- // Moving all tasks to fullscreen stack, because it's guaranteed to be
- // a valid launch stack for all activities. This way the task history from
- // external display will be preserved on primary after move.
- mSupervisor.moveTasksToFullscreenStackLocked(stack, true /* onTop */);
+ // If default display is in split-window mode, set windowing mode of the stack to
+ // split-screen secondary. Otherwise, set the windowing mode to undefined by
+ // default to let stack inherited the windowing mode from the new display.
+ int windowingMode = mSupervisor.getDefaultDisplay().hasSplitScreenPrimaryStack()
+ ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_UNDEFINED;
+ mSupervisor.moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, true);
+ stack.setWindowingMode(windowingMode);
}
}
+ mRemoved = true;
- mWindowContainerController.removeContainer();
- mWindowContainerController = null;
+ releaseSelfIfNeeded();
+ }
+
+ private void releaseSelfIfNeeded() {
+ if (mStacks.isEmpty() && mRemoved) {
+ mWindowContainerController.removeContainer();
+ mWindowContainerController = null;
+ mSupervisor.releaseActivityDisplayLocked(mDisplayId);
+ }
}
/** Update and get all UIDs that are present on the display and have access to it. */
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index fbf2855..78fef65 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -36,6 +36,15 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
import static com.android.server.am.ActivityDisplay.POSITION_TOP;
@@ -82,10 +91,6 @@
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
-import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
-import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.ActivityStackProto.BOUNDS;
import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
@@ -93,15 +98,10 @@
import static com.android.server.am.ActivityStackProto.ID;
import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityStackProto.TASKS;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
+import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static java.lang.Integer.MAX_VALUE;
@@ -115,12 +115,12 @@
import android.app.WindowConfiguration.WindowingMode;
import android.app.servertransaction.ActivityResultItem;
import android.app.servertransaction.ClientTransaction;
-import android.app.servertransaction.NewIntentItem;
-import android.app.servertransaction.WindowVisibilityItem;
import android.app.servertransaction.DestroyActivityItem;
+import android.app.servertransaction.NewIntentItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.StopActivityItem;
+import android.app.servertransaction.WindowVisibilityItem;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -5191,7 +5191,7 @@
if (isAttached()) {
getDisplay().positionChildAtBottom(this);
}
- if (!isActivityTypeHome()) {
+ if (!isActivityTypeHome() || getDisplay().isRemoved()) {
remove();
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9809bfa..4cfcbee 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -48,6 +48,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.TYPE_VIRTUAL;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -81,13 +82,6 @@
import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
-import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
-import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
-import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
@@ -95,7 +89,13 @@
import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
+import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import static java.lang.Integer.MAX_VALUE;
@@ -109,8 +109,6 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal;
-import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
import android.app.ActivityOptions;
import android.app.AppOpsManager;
import android.app.ProfilerInfo;
@@ -170,11 +168,13 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
-import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.os.TransferPipe;
+import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
import com.android.server.wm.ConfigurationContainer;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.WindowManagerService;
@@ -1862,7 +1862,7 @@
}
final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(launchDisplayId);
- if (activityDisplay == null) {
+ if (activityDisplay == null || activityDisplay.isRemoved()) {
Slog.w(TAG, "Launch on display check: display not found");
return false;
}
@@ -4359,11 +4359,14 @@
activityDisplay.remove();
releaseSleepTokens(activityDisplay);
-
- mActivityDisplays.remove(displayId);
}
}
+ void releaseActivityDisplayLocked(int displayId) {
+ mActivityDisplays.remove(displayId);
+ }
+
+
private void handleDisplayChanged(int displayId) {
synchronized (mService.mGlobalLock) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 65ee18a..ab38f65 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -20,7 +20,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -59,12 +58,25 @@
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static com.android.server.wm.DisplayContentProto.ABOVE_APP_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.BELOW_APP_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES;
+import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
+import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
+import static com.android.server.wm.DisplayContentProto.DPI;
+import static com.android.server.wm.DisplayContentProto.ID;
+import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
+import static com.android.server.wm.DisplayContentProto.ROTATION;
+import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
+import static com.android.server.wm.DisplayContentProto.STACKS;
+import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
@@ -101,19 +113,7 @@
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.DisplayContentProto.ABOVE_APP_WINDOWS;
-import static com.android.server.wm.DisplayContentProto.BELOW_APP_WINDOWS;
-import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES;
-import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
-import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
-import static com.android.server.wm.DisplayContentProto.DPI;
-import static com.android.server.wm.DisplayContentProto.ID;
-import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
-import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
-import static com.android.server.wm.DisplayContentProto.ROTATION;
-import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
-import static com.android.server.wm.DisplayContentProto.STACKS;
-import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
+import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
import android.annotation.CallSuper;
import android.annotation.NonNull;
@@ -3469,16 +3469,12 @@
private void addStackReferenceIfNeeded(TaskStack stack) {
if (stack.isActivityTypeHome()) {
- // TODO(b/111363427) Rollback to throws exceptions once we figure out how to
- // properly deal with home type stack when external display removed
if (mHomeStack != null) {
- // throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
- // + mHomeStack + " already exist on display=" + this + " stack=" + stack);
- Slog.e(TAG, "addStackReferenceIfNeeded: home stack="
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+ mHomeStack + " already exist on display=" + this + " stack=" + stack);
- } else {
- mHomeStack = stack;
+
}
+ mHomeStack = stack;
}
final int windowingMode = stack.getWindowingMode();
if (windowingMode == WINDOWING_MODE_PINNED) {