Don't allow non-dockable activities/tasks in docked stack.
Prevent activities and tasks that are not resizeable and don't
support crop windows resize mode from going into the docked stack.
Bug: 26774816
Change-Id: I1fd23114685be15908e80e8bc5a0216d8bfd049e
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 133ac38..ed26e0c 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -18,6 +18,7 @@
import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
@@ -759,10 +760,19 @@
return !isHomeActivity() && ActivityInfo.isResizeableMode(info.resizeMode);
}
+ boolean isResizeableOrForced() {
+ return !isHomeActivity() && (isResizeable() || service.mForceResizableActivities);
+ }
+
boolean supportsPictureInPicture() {
return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
}
+ boolean canGoInDockedStack() {
+ return !isHomeActivity()
+ && (isResizeableOrForced() || info.resizeMode == RESIZE_MODE_CROP_WINDOWS);
+ }
+
boolean isAlwaysFocusable() {
return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index dac0f7d0..b9b2bb6 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1414,8 +1414,7 @@
// task in the focus stack doesn't support any form of resizing.
final ActivityRecord r = focusedStack.topRunningActivityLocked();
final TaskRecord task = r != null ? r.task : null;
- return task == null || task.isResizeable() || task.inCropWindowsResizeMode()
- ? STACK_VISIBLE : STACK_INVISIBLE;
+ return task == null || task.canGoInDockedStack() ? STACK_VISIBLE : STACK_INVISIBLE;
}
// Find the first stack below focused stack that actually got something visible.
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1660dda..828cb53 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1723,7 +1723,9 @@
stackId = task.getLaunchStackId();
}
if (stackId != task.stack.mStackId) {
- moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason);
+ final ActivityStack stack = moveTaskToStackUncheckedLocked(
+ task, stackId, ON_TOP, !FORCE_FOCUS, reason);
+ stackId = stack.mStackId;
// moveTaskToStackUncheckedLocked() should already placed the task on top,
// still need moveTaskToFrontLocked() below for any transition settings.
}
@@ -2133,7 +2135,12 @@
private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
if (stackId == INVALID_STACK_ID) {
stackId = task.getLaunchStackId();
+ } else if (stackId == DOCKED_STACK_ID && !task.canGoInDockedStack()) {
+ // Preferred stack is the docked stack, but the task can't go in the docked stack.
+ // Put it in the fullscreen stack.
+ stackId = FULLSCREEN_WORKSPACE_STACK_ID;
}
+
if (task.stack != null) {
// Task has already been restored once. See if we need to do anything more
if (task.stack.mStackId == stackId) {
@@ -2169,8 +2176,7 @@
* Moves the specified task record to the input stack id.
* WARNING: This method performs an unchecked/raw move of the task and
* can leave the system in an unstable state if used incorrectly.
- * Use {@link #moveTaskToStackLocked} to perform safe task movement
- * to a stack.
+ * Use {@link #moveTaskToStackLocked} to perform safe task movement to a stack.
* @param task Task to move.
* @param stackId Id of stack to move task to.
* @param toTop True if the task should be placed at the top of the stack.
@@ -2191,6 +2197,18 @@
&& (prevStack.topRunningActivityLocked() == r);
final int resizeMode = task.mResizeMode;
+
+ if (stackId == DOCKED_STACK_ID && resizeMode == RESIZE_MODE_UNRESIZEABLE) {
+ // We don't allow moving a unresizeable task to the docked stack since the docked
+ // stack is used for split-screen mode and will cause things like the docked divider to
+ // show up. We instead leave the task in its current stack or move it to the fullscreen
+ // stack if it isn't currently in a stack.
+ stackId = (prevStack != null) ? prevStack.mStackId : FULLSCREEN_WORKSPACE_STACK_ID;
+ // TODO: display toast that activity doesn't support multi-window mode.
+ Slog.w(TAG, "Can not move unresizeable task=" + task
+ + " to docked stack. Moving to stackId=" + stackId + " instead.");
+ }
+
// Temporarily disable resizeablility of task we are moving. We don't want it to be resized
// if a docked stack is created below which will lead to the stack we are moving from and
// its resizeable tasks being resized.
@@ -2238,6 +2256,7 @@
}
final ActivityStack stack = moveTaskToStackUncheckedLocked(
task, stackId, toTop, forceFocus, "moveTaskToStack:" + reason);
+ stackId = stack.mStackId;
if (!animate) {
stack.mNoAnimActivities.add(topActivity);
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 22b8462..76f3516 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1484,8 +1484,9 @@
mInTask.updateOverrideConfiguration(mLaunchBounds);
int stackId = mInTask.getLaunchStackId();
if (stackId != mInTask.stack.mStackId) {
- mSupervisor.moveTaskToStackUncheckedLocked(
+ final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
+ stackId = stack.mStackId;
}
if (StackId.resizeStackWithLaunchBounds(stackId)) {
mSupervisor.resizeStackLocked(stackId, mLaunchBounds,
@@ -1627,10 +1628,9 @@
// If the freeform or docked stack has focus, and the activity to be launched is resizeable,
// we can also put it in the focused stack.
final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
- final boolean canUseFocusedStack =
- focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
- || focusedStackId == DOCKED_STACK_ID
- || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeable());
+ final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
+ || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
+ || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
if (canUseFocusedStack && (!newTask
|| mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
@@ -1666,6 +1666,10 @@
if (isValidLaunchStackId(launchStackId, r)) {
return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
+ } else if (launchStackId == DOCKED_STACK_ID) {
+ // The preferred launch stack is the docked stack, but it isn't a valid launch stack
+ // for this activity, so we put the activity in the fullscreen stack.
+ return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_TO_SIDE) == 0) {
@@ -1701,9 +1705,11 @@
return false;
}
- final boolean resizeable = r.isResizeable() || mService.mForceResizableActivities;
+ if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
+ return true;
+ }
- if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !resizeable) {
+ if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !r.isResizeableOrForced()) {
return false;
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index c14cfef..be97c5a 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -943,6 +943,10 @@
return !isResizeable() && mResizeMode == RESIZE_MODE_CROP_WINDOWS;
}
+ boolean canGoInDockedStack() {
+ return isResizeable() || inCropWindowsResizeMode();
+ }
+
/**
* Find the activity in the history stack within the given task. Returns
* the index within the history at which it's found, or < 0 if not found.