Merge "Moved ActivityDisplay to its own class file."
diff --git a/api/test-current.txt b/api/test-current.txt
index 2c6dcaa..90ecb8c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3866,6 +3866,8 @@
method public deprecated void restartPackage(java.lang.String);
method public static void setVrThread(int);
method public void setWatchHeapLimit(long);
+ method public static boolean supportsMultiWindow(android.content.Context);
+ method public static boolean supportsSplitScreenMultiWindow(android.content.Context);
field public static final java.lang.String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT";
field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1
field public static final int LOCK_TASK_MODE_NONE = 0; // 0x0
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 78d05f5..5e2e333 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1152,6 +1152,7 @@
* E.g. freeform, split-screen, picture-in-picture.
* @hide
*/
+ @TestApi
static public boolean supportsMultiWindow(Context context) {
// On watches, multi-window is used to present essential system UI, and thus it must be
// supported regardless of device memory characteristics.
@@ -1166,6 +1167,7 @@
* Returns true if the system supports split screen multi-window.
* @hide
*/
+ @TestApi
static public boolean supportsSplitScreenMultiWindow(Context context) {
return supportsMultiWindow(context)
&& Resources.getSystem().getBoolean(
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
new file mode 100644
index 0000000..5da9fb2
--- /dev/null
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static android.view.Display.FLAG_PRIVATE;
+import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.proto.ActivityDisplayProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.proto.ActivityDisplayProto.STACKS;
+import static com.android.server.am.proto.ActivityDisplayProto.ID;
+
+import android.app.ActivityManagerInternal;
+import android.util.IntArray;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+import android.view.Display;
+import com.android.server.wm.ConfigurationContainer;
+
+import java.util.ArrayList;
+
+/**
+ * Exactly one of these classes per Display in the system. Capable of holding zero or more
+ * attached {@link ActivityStack}s.
+ */
+class ActivityDisplay extends ConfigurationContainer {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
+ private static final String TAG_STACK = TAG + POSTFIX_STACK;
+
+ static final int POSITION_TOP = Integer.MAX_VALUE;
+ static final int POSITION_BOTTOM = Integer.MIN_VALUE;
+
+ private ActivityStackSupervisor mSupervisor;
+ /** Actual Display this object tracks. */
+ int mDisplayId;
+ Display mDisplay;
+
+ /** All of the stacks on this display. Order matters, topmost stack is in front of all other
+ * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
+ final ArrayList<ActivityStack> mStacks = new ArrayList<>();
+
+ /** Array of all UIDs that are present on the display. */
+ private IntArray mDisplayAccessUIDs = new IntArray();
+
+ /** All tokens used to put activities on this stack to sleep (including mOffToken) */
+ final ArrayList<ActivityManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>();
+ /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */
+ ActivityManagerInternal.SleepToken mOffToken;
+
+ private boolean mSleeping;
+
+ ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
+ mSupervisor = supervisor;
+ mDisplayId = displayId;
+ final Display display = supervisor.mDisplayManager.getDisplay(displayId);
+ if (display == null) {
+ throw new IllegalStateException("Display does not exist displayId=" + displayId);
+ }
+ mDisplay = display;
+ }
+
+ void addChild(ActivityStack stack, int position) {
+ if (position == POSITION_BOTTOM) {
+ position = 0;
+ } else if (position == POSITION_TOP) {
+ position = mStacks.size();
+ }
+ if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
+ + " to displayId=" + mDisplayId + " position=" + position);
+ positionChildAt(stack, position);
+ mSupervisor.mService.updateSleepIfNeededLocked();
+ }
+
+ void removeChild(ActivityStack stack) {
+ if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
+ + " from displayId=" + mDisplayId);
+ mStacks.remove(stack);
+ mSupervisor.mService.updateSleepIfNeededLocked();
+ }
+
+ void positionChildAtTop(ActivityStack stack) {
+ positionChildAt(stack, mStacks.size());
+ }
+
+ void positionChildAtBottom(ActivityStack stack) {
+ positionChildAt(stack, 0);
+ }
+
+ private void positionChildAt(ActivityStack stack, int position) {
+ mStacks.remove(stack);
+ mStacks.add(getTopInsertPosition(stack, position), stack);
+ }
+
+ private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
+ int position = mStacks.size();
+ if (position > 0) {
+ final ActivityStack topStack = mStacks.get(position - 1);
+ if (topStack.getWindowConfiguration().isAlwaysOnTop() && topStack != stack) {
+ // If the top stack is always on top, we move this stack just below it.
+ position--;
+ }
+ }
+ return Math.min(position, candidatePosition);
+ }
+
+ <T extends ActivityStack> T getStack(int stackId) {
+ for (int i = mStacks.size() - 1; i >= 0; --i) {
+ final ActivityStack stack = mStacks.get(i);
+ if (stack.mStackId == stackId) {
+ return (T) stack;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
+ }
+
+ @Override
+ protected int getChildCount() {
+ return mStacks.size();
+ }
+
+ @Override
+ protected ConfigurationContainer getChildAt(int index) {
+ return mStacks.get(index);
+ }
+
+ @Override
+ protected ConfigurationContainer getParent() {
+ return mSupervisor;
+ }
+
+ boolean isPrivate() {
+ return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
+ }
+
+ boolean isUidPresent(int uid) {
+ for (ActivityStack stack : mStacks) {
+ if (stack.isUidPresent(uid)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Update and get all UIDs that are present on the display and have access to it. */
+ IntArray getPresentUIDs() {
+ mDisplayAccessUIDs.clear();
+ for (ActivityStack stack : mStacks) {
+ stack.getPresentUIDs(mDisplayAccessUIDs);
+ }
+ return mDisplayAccessUIDs;
+ }
+
+ boolean shouldDestroyContentOnRemove() {
+ return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
+ }
+
+ boolean shouldSleep() {
+ return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
+ && (mSupervisor.mService.mRunningVoice == null);
+ }
+
+ boolean isSleeping() {
+ return mSleeping;
+ }
+
+ void setIsSleeping(boolean asleep) {
+ mSleeping = asleep;
+ }
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER);
+ proto.write(ID, mDisplayId);
+ for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = mStacks.get(stackNdx);
+ stack.writeToProto(proto, STACKS);
+ }
+ proto.end(token);
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 12778d8..6df5fb7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -20060,7 +20060,10 @@
synchronized (this) {
final long origId = Binder.clearCallingIdentity();
try {
- mStackSupervisor.moveTasksToFullscreenStackLocked(fromStackId, onTop);
+ final ActivityStack stack = mStackSupervisor.getStack(fromStackId);
+ if (stack != null){
+ mStackSupervisor.moveTasksToFullscreenStackLocked(stack, onTop);
+ }
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 142c97b..2241ed6 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -2312,7 +2312,7 @@
// be visible based on the stack, task, and lockscreen state and use that here instead. The
// method should be based on the logic in ActivityStack.ensureActivitiesVisibleLocked().
// Skip updating configuration for activity is a stack that shouldn't be visible.
- if (stack.shouldBeVisible(null /* starting */) == STACK_INVISIBLE) {
+ if (!stack.shouldBeVisible(null /* starting */)) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Skipping config check invisible stack: " + this);
return true;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 8d21862..361d91a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -29,6 +29,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
@@ -37,6 +38,8 @@
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
+import static com.android.server.am.ActivityDisplay.POSITION_TOP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
@@ -267,7 +270,6 @@
final ActivityManagerService mService;
private final WindowManagerService mWindowManager;
T mWindowContainerController;
- private final RecentTasks mRecentTasks;
/**
* The back history of all previous (and possibly still
@@ -350,9 +352,6 @@
int mCurrentUser;
final int mStackId;
- /** The other stacks, in order, on the attached display. Updated at attach/detach time. */
- // TODO: This list doesn't belong here...
- ArrayList<ActivityStack> mStacks;
/** The attached Display's unique identifier, or -1 if detached */
int mDisplayId;
@@ -461,22 +460,20 @@
return count;
}
- ActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId,
- ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) {
+ ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
+ boolean onTop) {
mStackSupervisor = supervisor;
mService = supervisor.mService;
mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
mWindowManager = mService.mWindowManager;
mStackId = stackId;
mCurrentUser = mService.mUserController.getCurrentUserIdLocked();
- mRecentTasks = recentTasks;
mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
? new LaunchingTaskPositioner() : null;
mTmpRect2.setEmpty();
updateOverrideConfiguration();
mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
mTmpRect2);
- mStackSupervisor.mStacks.put(mStackId, this);
postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
}
@@ -503,7 +500,7 @@
}
/** Adds the stack to specified display and calls WindowManager to do the same. */
- void reparent(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
+ void reparent(ActivityDisplay activityDisplay, boolean onTop) {
removeFromDisplay();
mTmpRect2.setEmpty();
postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
@@ -521,10 +518,9 @@
* @param activityDisplay New display to which this stack was attached.
* @param bounds Updated bounds.
*/
- private void postAddToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay,
+ private void postAddToDisplay(ActivityDisplay activityDisplay,
Rect bounds, boolean onTop) {
mDisplayId = activityDisplay.mDisplayId;
- mStacks = activityDisplay.mStacks;
mBounds = bounds != null ? new Rect(bounds) : null;
mFullscreen = mBounds == null;
if (mTaskPositioner != null) {
@@ -533,7 +529,7 @@
}
onParentChanged();
- activityDisplay.attachStack(this, findStackInsertIndex(onTop));
+ activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
if (mStackId == DOCKED_STACK_ID) {
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
@@ -547,33 +543,31 @@
* either destroyed completely or re-parented.
*/
private void removeFromDisplay() {
- final ActivityStackSupervisor.ActivityDisplay display = getDisplay();
- if (display != null) {
- display.detachStack(this);
- }
- mDisplayId = INVALID_DISPLAY;
- mStacks = null;
- if (mTaskPositioner != null) {
- mTaskPositioner.reset();
- }
- if (mStackId == DOCKED_STACK_ID) {
+ if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// If we removed a docked stack we want to resize it so it resizes all other stacks
// in the system to fullscreen.
mStackSupervisor.resizeDockedStackLocked(
null, null, null, null, null, PRESERVE_WINDOWS);
}
+ final ActivityDisplay display = getDisplay();
+ if (display != null) {
+ display.removeChild(this);
+ }
+ mDisplayId = INVALID_DISPLAY;
+ if (mTaskPositioner != null) {
+ mTaskPositioner.reset();
+ }
}
/** Removes the stack completely. Also calls WindowManager to do the same on its side. */
void remove() {
removeFromDisplay();
- mStackSupervisor.mStacks.remove(mStackId);
mWindowContainerController.removeContainer();
mWindowContainerController = null;
onParentChanged();
}
- ActivityStackSupervisor.ActivityDisplay getDisplay() {
+ ActivityDisplay getDisplay() {
return mStackSupervisor.getActivityDisplay(mDisplayId);
}
@@ -858,7 +852,7 @@
}
final boolean isOnHomeDisplay() {
- return isAttached() && mDisplayId == DEFAULT_DISPLAY;
+ return mDisplayId == DEFAULT_DISPLAY;
}
void moveToFront(String reason) {
@@ -874,8 +868,7 @@
return;
}
- mStacks.remove(this);
- mStacks.add(findStackInsertIndex(ON_TOP), this);
+ getDisplay().positionChildAtTop(this);
mStackSupervisor.setFocusStackUnchecked(reason, this);
if (task != null) {
insertTaskAtTop(task, null);
@@ -889,45 +882,6 @@
}
}
- /**
- * @param task If non-null, the task will be moved to the back of the stack.
- * */
- private void moveToBack(TaskRecord task) {
- if (!isAttached()) {
- return;
- }
-
- mStacks.remove(this);
- mStacks.add(0, this);
-
- if (task != null) {
- mTaskHistory.remove(task);
- mTaskHistory.add(0, task);
- updateTaskMovement(task, false);
- mWindowContainerController.positionChildAtBottom(task.getWindowContainerController());
- }
- }
-
- /**
- * @return the index to insert a new stack into, taking the always-on-top stacks into account.
- */
- private int findStackInsertIndex(boolean onTop) {
- if (onTop) {
- int addIndex = mStacks.size();
- if (addIndex > 0) {
- final ActivityStack topStack = mStacks.get(addIndex - 1);
- if (topStack.getWindowConfiguration().isAlwaysOnTop()
- && topStack != this) {
- // If the top stack is always on top, we move this stack just below it.
- addIndex--;
- }
- }
- return addIndex;
- } else {
- return 0;
- }
- }
-
boolean isFocusable() {
if (getWindowConfiguration().canReceiveKeys()) {
return true;
@@ -939,7 +893,7 @@
}
final boolean isAttached() {
- return mStacks != null;
+ return getParent() != null;
}
/**
@@ -1114,13 +1068,6 @@
"Launch completed; removing icicle of " + r.icicle);
}
- void addRecentActivityLocked(ActivityRecord r) {
- if (r != null) {
- final TaskRecord task = r.getTask();
- mRecentTasks.addLocked(task);
- task.touchActiveTime();
- }
- }
private void startLaunchTraces(String packageName) {
if (mFullyDrawnStartTime != 0) {
@@ -1568,54 +1515,6 @@
}
}
- // Find the first visible activity above the passed activity and if it is translucent return it
- // otherwise return null;
- ActivityRecord findNextTranslucentActivity(ActivityRecord r) {
- TaskRecord task = r.getTask();
- if (task == null) {
- return null;
- }
-
- final ActivityStack stack = task.getStack();
- if (stack == null) {
- return null;
- }
-
- int stackNdx = mStacks.indexOf(stack);
-
- ArrayList<TaskRecord> tasks = stack.mTaskHistory;
- int taskNdx = tasks.indexOf(task);
-
- ArrayList<ActivityRecord> activities = task.mActivities;
- int activityNdx = activities.indexOf(r) + 1;
-
- final int numStacks = mStacks.size();
- while (stackNdx < numStacks) {
- final ActivityStack historyStack = mStacks.get(stackNdx);
- tasks = historyStack.mTaskHistory;
- final int numTasks = tasks.size();
- while (taskNdx < numTasks) {
- final TaskRecord currentTask = tasks.get(taskNdx);
- activities = currentTask.mActivities;
- final int numActivities = activities.size();
- while (activityNdx < numActivities) {
- final ActivityRecord activity = activities.get(activityNdx);
- if (!activity.finishing) {
- return historyStack.mFullscreen
- && currentTask.mFullscreen && activity.fullscreen ? null : activity;
- }
- ++activityNdx;
- }
- activityNdx = 0;
- ++taskNdx;
- }
- taskNdx = 0;
- ++stackNdx;
- }
-
- return null;
- }
-
/** Returns true if the stack contains a fullscreen task. */
private boolean hasFullscreenTask() {
for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
@@ -1679,26 +1578,26 @@
}
/**
- * Returns what the stack visibility should be: {@link #STACK_INVISIBLE} or
- * {@link #STACK_VISIBLE}.
+ * Returns true if the stack should be visible.
*
* @param starting The currently starting activity or null if there is none.
*/
- int shouldBeVisible(ActivityRecord starting) {
+ boolean shouldBeVisible(ActivityRecord starting) {
if (!isAttached() || mForceHidden) {
- return STACK_INVISIBLE;
+ return false;
}
if (mStackSupervisor.isFrontStackOnDisplay(this) || mStackSupervisor.isFocusedStack(this)) {
- return STACK_VISIBLE;
+ return true;
}
- final int stackIndex = mStacks.indexOf(this);
+ final ArrayList<ActivityStack> displayStacks = getDisplay().mStacks;
+ final int stackIndex = displayStacks.indexOf(this);
- if (stackIndex == mStacks.size() - 1) {
+ if (stackIndex == displayStacks.size() - 1) {
Slog.wtf(TAG,
"Stack=" + this + " isn't front stack but is at the top of the stack list");
- return STACK_INVISIBLE;
+ return false;
}
// Check position and visibility of this stack relative to the front stack on its display.
@@ -1709,43 +1608,43 @@
// If the assistant stack is focused and translucent, then the docked stack is always
// visible
if (topStack.isActivityTypeAssistant()) {
- return (topStack.isStackTranslucent(starting, DOCKED_STACK_ID)) ? STACK_VISIBLE
- : STACK_INVISIBLE;
+ return topStack.isStackTranslucent(starting, DOCKED_STACK_ID);
}
- return STACK_VISIBLE;
+ return true;
}
// Set home stack to invisible when it is below but not immediately below the docked stack
// A case would be if recents stack exists but has no tasks and is below the docked stack
// and home stack is below recents
if (mStackId == HOME_STACK_ID) {
- int dockedStackIndex = mStacks.indexOf(mStackSupervisor.getStack(DOCKED_STACK_ID));
+ int dockedStackIndex = displayStacks.indexOf
+ (mStackSupervisor.getStack(DOCKED_STACK_ID));
if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) {
- return STACK_INVISIBLE;
+ return false;
}
}
// Find the first stack behind front stack that actually got something visible.
- int stackBehindTopIndex = mStacks.indexOf(topStack) - 1;
+ int stackBehindTopIndex = displayStacks.indexOf(topStack) - 1;
while (stackBehindTopIndex >= 0 &&
- mStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
+ displayStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
stackBehindTopIndex--;
}
final int stackBehindTopId = (stackBehindTopIndex >= 0)
- ? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
+ ? displayStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop();
if (topStackId == DOCKED_STACK_ID || alwaysOnTop) {
if (stackIndex == stackBehindTopIndex) {
// Stacks directly behind the docked or pinned stack are always visible.
- return STACK_VISIBLE;
+ return true;
} else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) {
// Otherwise, this stack can also be visible if it is directly behind a docked stack
// or translucent assistant stack behind an always-on-top top-most stack
if (stackBehindTopId == DOCKED_STACK_ID) {
- return STACK_VISIBLE;
+ return true;
} else if (stackBehindTopId == ASSISTANT_STACK_ID) {
- return mStacks.get(stackBehindTopIndex).isStackTranslucent(starting, mStackId)
- ? STACK_VISIBLE : STACK_INVISIBLE;
+ return displayStacks.get(stackBehindTopIndex).isStackTranslucent(
+ starting, mStackId);
}
}
}
@@ -1756,7 +1655,7 @@
// always visible so they can act as a backdrop to the translucent activity.
// For example, dialog activities
if (stackIndex == stackBehindTopIndex) {
- return STACK_VISIBLE;
+ return true;
}
if (stackBehindTopIndex >= 0) {
if ((stackBehindTopId == DOCKED_STACK_ID
@@ -1764,18 +1663,18 @@
&& stackIndex == (stackBehindTopIndex - 1)) {
// The stack behind the docked or pinned stack is also visible so we can have a
// complete backdrop to the translucent activity when the docked stack is up.
- return STACK_VISIBLE;
+ return true;
}
}
}
if (StackId.isStaticStack(mStackId)) {
// Visibility of any static stack should have been determined by the conditions above.
- return STACK_INVISIBLE;
+ return false;
}
- for (int i = stackIndex + 1; i < mStacks.size(); i++) {
- final ActivityStack stack = mStacks.get(i);
+ for (int i = stackIndex + 1; i < displayStacks.size(); i++) {
+ final ActivityStack stack = displayStacks.get(i);
if (!stack.mFullscreen && !stack.hasFullscreenTask()) {
continue;
@@ -1783,15 +1682,15 @@
if (!StackId.isDynamicStacksVisibleBehindAllowed(stack.mStackId)) {
// These stacks can't have any dynamic stacks visible behind them.
- return STACK_INVISIBLE;
+ return false;
}
if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) {
- return STACK_INVISIBLE;
+ return false;
}
}
- return STACK_VISIBLE;
+ return true;
}
final int rankTaskLayers(int baseLayer) {
@@ -1828,12 +1727,10 @@
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
boolean aboveTop = top != null;
- final int stackVisibility = shouldBeVisible(starting);
- final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
- boolean behindFullscreenActivity = stackInvisible;
+ final boolean stackVisible = shouldBeVisible(starting);
+ boolean behindFullscreenActivity = !stackVisible;
boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
&& (isInStackLocked(starting) == null);
- boolean behindTranslucentActivity = false;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -1857,11 +1754,8 @@
final boolean reallyVisible = checkKeyguardVisibility(r,
visibleIgnoringKeyguard, isTop);
if (visibleIgnoringKeyguard) {
- behindFullscreenActivity = updateBehindFullscreen(stackInvisible,
+ behindFullscreenActivity = updateBehindFullscreen(!stackVisible,
behindFullscreenActivity, task, r);
- if (behindFullscreenActivity && !r.fullscreen) {
- behindTranslucentActivity = true;
- }
}
if (reallyVisible) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
@@ -1897,10 +1791,10 @@
configChanges |= r.configChangeFlags;
} else {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
- + " finishing=" + r.finishing + " state=" + r.state + " stackInvisible="
- + stackInvisible + " behindFullscreenActivity="
- + behindFullscreenActivity + " mLaunchTaskBehind="
- + r.mLaunchTaskBehind);
+ + " finishing=" + r.finishing + " state=" + r.state
+ + " stackVisible=" + stackVisible
+ + " behindFullscreenActivity=" + behindFullscreenActivity
+ + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
makeInvisible(r);
}
}
@@ -1908,10 +1802,10 @@
// The visibility of tasks and the activities they contain in freeform stack are
// determined individually unlike other stacks where the visibility or fullscreen
// status of an activity in a previous task affects other.
- behindFullscreenActivity = stackVisibility == STACK_INVISIBLE;
+ behindFullscreenActivity = !stackVisible;
} else if (mStackId == HOME_STACK_ID) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
- + " stackInvisible=" + stackInvisible
+ + " stackVisible=" + stackVisible
+ " behindFullscreenActivity=" + behindFullscreenActivity);
// No other task in the home stack should be visible behind the home activity.
// Home activities is usually a translucent activity with the wallpaper behind
@@ -2012,7 +1906,7 @@
* {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
*/
private boolean canShowWithInsecureKeyguard() {
- final ActivityStackSupervisor.ActivityDisplay activityDisplay = getDisplay();
+ final ActivityDisplay activityDisplay = getDisplay();
if (activityDisplay == null) {
throw new IllegalStateException("Stack is not attached to any display, stackId="
+ mStackId);
@@ -2192,7 +2086,7 @@
// activities as we need to display their starting window until they are done initializing.
boolean behindFullscreenActivity = false;
- if (shouldBeVisible(null) == STACK_INVISIBLE) {
+ if (!shouldBeVisible(null)) {
// The stack is not visible, so no activity in it should be displaying a starting
// window. Mark all activities below top and behind fullscreen.
aboveTop = false;
@@ -2268,9 +2162,7 @@
mResumedActivity = r;
r.state = ActivityState.RESUMED;
mService.setResumedActivityUncheckLocked(r, reason);
- final TaskRecord task = r.getTask();
- task.touchActiveTime();
- mRecentTasks.addLocked(task);
+ mStackSupervisor.addRecentActivity(r);
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
@@ -4558,7 +4450,7 @@
// Don't refocus if invisible to current user
final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
- addRecentActivityLocked(top);
+ mStackSupervisor.addRecentActivity(top);
ActivityOptions.abort(options);
return;
}
@@ -5162,8 +5054,7 @@
if (task.autoRemoveFromRecents() || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
- mRecentTasks.remove(task);
- task.removedFromRecents();
+ mStackSupervisor.removeTaskFromRecents(task);
}
task.removeWindowContainer();
@@ -5180,9 +5071,8 @@
mStackSupervisor.moveHomeStackToFront(myReason);
}
}
- if (mStacks != null) {
- mStacks.remove(this);
- mStacks.add(0, this);
+ if (isAttached()) {
+ getDisplay().positionChildAtBottom(this);
}
if (!isHomeOrRecentsStack()) {
remove();
@@ -5359,7 +5249,7 @@
}
boolean shouldSleepActivities() {
- final ActivityStackSupervisor.ActivityDisplay display = getDisplay();
+ final ActivityDisplay display = getDisplay();
return display != null ? display.isSleeping() : mService.isSleepingLocked();
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 45c4df9..bf0c3a4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -52,9 +52,7 @@
import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
import static android.view.Display.TYPE_VIRTUAL;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
@@ -393,15 +391,11 @@
* They are used by components that may hide and block interaction with underlying
* activities.
*/
- final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>();
+ final ArrayList<SleepToken> mSleepTokens = new ArrayList<>();
/** Stack id of the front stack when user switched, indexed by userId. */
SparseIntArray mUserStackInFront = new SparseIntArray(2);
- // TODO: Add listener for removal of references.
- /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
- SparseArray<ActivityStack> mStacks = new SparseArray<>();
-
// TODO: There should be an ActivityDisplayController coordinating am/wm interaction.
/** Mapping from displayId to display current state */
private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>();
@@ -620,10 +614,7 @@
Display[] displays = mDisplayManager.getDisplays();
for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
final int displayId = displays[displayNdx].getDisplayId();
- ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
- if (activityDisplay.mDisplay == null) {
- throw new IllegalStateException("Default Display does not exist");
- }
+ ActivityDisplay activityDisplay = new ActivityDisplay(this, displayId);
mActivityDisplays.put(displayId, activityDisplay);
calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
}
@@ -2160,12 +2151,18 @@
}
protected <T extends ActivityStack> T getStack(int stackId) {
- return getStack(stackId, !CREATE_IF_NEEDED, !ON_TOP);
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final T stack = mActivityDisplays.valueAt(i).getStack(stackId);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
}
protected <T extends ActivityStack> T getStack(int stackId, boolean createStaticStackIfNeeded,
boolean createOnTop) {
- final ActivityStack stack = mStacks.get(stackId);
+ final ActivityStack stack = getStack(stackId);
if (stack != null) {
return (T) stack;
}
@@ -2443,8 +2440,7 @@
final List<ActivityStack> stacks = getActivityDisplayOrCreateLocked(displayId).mStacks;
for (int j = stacks.size() - 1; j >= 0; --j) {
final ActivityStack stack = stacks.get(j);
- if (stack != currentFocus && stack.isFocusable()
- && stack.shouldBeVisible(null) != STACK_INVISIBLE) {
+ if (stack != currentFocus && stack.isFocusable() && stack.shouldBeVisible(null)) {
return stack;
}
}
@@ -2571,16 +2567,12 @@
mResizingTasksDuringAnimation.clear();
}
- private void moveTasksToFullscreenStackInSurfaceTransaction(int fromStackId,
+ private void moveTasksToFullscreenStackInSurfaceTransaction(ActivityStack fromStack,
boolean onTop) {
- final ActivityStack stack = getStack(fromStackId);
- if (stack == null) {
- return;
- }
-
mWindowManager.deferSurfaceLayout();
try {
+ final int fromStackId = fromStack.mStackId;
if (fromStackId == DOCKED_STACK_ID) {
// We are moving all tasks from the docked stack to the fullscreen stack,
// which is dismissing the docked stack, so resize all other stacks to
@@ -2610,12 +2602,12 @@
}
}
ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
- final boolean isFullscreenStackVisible = fullscreenStack != null &&
- fullscreenStack.shouldBeVisible(null) == STACK_VISIBLE;
+ final boolean isFullscreenStackVisible = fullscreenStack != null
+ && fullscreenStack.shouldBeVisible(null);
// If we are moving from the pinned stack, then the animation takes care of updating
// the picture-in-picture mode.
final boolean schedulePictureInPictureModeChange = (fromStackId == PINNED_STACK_ID);
- final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ final ArrayList<TaskRecord> tasks = fromStack.getAllTasks();
final int size = tasks.size();
if (onTop) {
for (int i = 0; i < size; i++) {
@@ -2655,9 +2647,9 @@
}
}
- void moveTasksToFullscreenStackLocked(int fromStackId, boolean onTop) {
+ void moveTasksToFullscreenStackLocked(ActivityStack fromStack, boolean onTop) {
mWindowManager.inSurfaceTransaction(
- () -> moveTasksToFullscreenStackInSurfaceTransaction(fromStackId, onTop));
+ () -> moveTasksToFullscreenStackInSurfaceTransaction(fromStack, onTop));
}
void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
@@ -2697,7 +2689,7 @@
// The dock stack either was dismissed or went fullscreen, which is kinda the same.
// In this case we make all other static stacks fullscreen and move all
// docked stack tasks to the fullscreen stack.
- moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, ON_TOP);
+ moveTasksToFullscreenStackLocked(stack, ON_TOP);
// stack shouldn't contain anymore activities, so nothing to resume.
r = null;
@@ -2789,9 +2781,9 @@
ActivityStack createStack(int stackId, ActivityDisplay display, boolean onTop) {
switch (stackId) {
case PINNED_STACK_ID:
- return new PinnedActivityStack(display, stackId, this, mRecentTasks, onTop);
+ return new PinnedActivityStack(display, stackId, this, onTop);
default:
- return new ActivityStack(display, stackId, this, mRecentTasks, onTop);
+ return new ActivityStack(display, stackId, this, onTop);
}
}
@@ -2820,7 +2812,7 @@
true /* processPausingActivites */, null /* configuration */);
// Move all the tasks to the bottom of the fullscreen stack
- moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
+ moveTasksToFullscreenStackLocked(pinnedStack, !ON_TOP);
} else {
for (int i = tasks.size() - 1; i >= 0; i--) {
removeTaskByIdLocked(tasks.get(i).taskId, true /* killProcess */,
@@ -2871,10 +2863,23 @@
return false;
}
+ void addRecentActivity(ActivityRecord r) {
+ if (r == null) {
+ return;
+ }
+ final TaskRecord task = r.getTask();
+ mRecentTasks.addLocked(task);
+ task.touchActiveTime();
+ }
+
+ void removeTaskFromRecents(TaskRecord task) {
+ mRecentTasks.remove(task);
+ task.removedFromRecents();
+ }
+
void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) {
if (removeFromRecents) {
- mRecentTasks.remove(tr);
- tr.removedFromRecents();
+ removeTaskFromRecents(tr);
}
ComponentName component = tr.getBaseIntent().getComponent();
if (component == null) {
@@ -3000,7 +3005,7 @@
throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId="
+ displayId);
}
- final ActivityStack stack = mStacks.get(stackId);
+ final ActivityStack stack = getStack(stackId);
if (stack == null) {
throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown stackId="
+ stackId);
@@ -3109,12 +3114,16 @@
mWindowManager.deferSurfaceLayout();
+ PinnedActivityStack stack = getStack(PINNED_STACK_ID);
+
// This will clear the pinned stack by moving an existing task to the full screen stack,
// ensuring only one task is present.
- moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
+ if (stack != null) {
+ moveTasksToFullscreenStackLocked(stack, !ON_TOP);
+ }
// Need to make sure the pinned stack exist so we can resize it below...
- final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
+ stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
try {
final TaskRecord task = r.getTask();
@@ -3608,7 +3617,10 @@
boolean switchUserLocked(int userId, UserState uss) {
final int focusStackId = mFocusedStack.getStackId();
// We dismiss the docked stack whenever we switch users.
- moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, focusStackId == DOCKED_STACK_ID);
+ final ActivityStack dockedStack = getStack(DOCKED_STACK_ID);
+ if (dockedStack != null) {
+ moveTasksToFullscreenStackLocked(dockedStack, mFocusedStack == dockedStack);
+ }
// Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
// also cause all tasks to be moved to the fullscreen stack at a position that is
// appropriate.
@@ -3755,7 +3767,10 @@
pw.print(prefix);
pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
- pw.print(prefix); pw.println("mStacks=" + mStacks);
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay display = mActivityDisplays.valueAt(i);
+ pw.println(prefix + "displayId=" + display.mDisplayId + " mStacks=" + display.mStacks);
+ }
if (!mWaitingForActivityVisible.isEmpty()) {
pw.print(prefix); pw.println("mWaitingForActivityVisible=");
for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) {
@@ -3816,8 +3831,7 @@
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
- if (!dumpVisibleStacksOnly ||
- stack.shouldBeVisible(null) == STACK_VISIBLE) {
+ if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
activities.addAll(stack.getDumpActivitiesLocked(name));
}
}
@@ -4066,17 +4080,18 @@
return null;
}
// The display hasn't been added to ActivityManager yet, create a new record now.
- activityDisplay = new ActivityDisplay(displayId);
- if (activityDisplay.mDisplay == null) {
- Slog.w(TAG, "Display " + displayId + " gone before initialization complete");
- return null;
- }
- mActivityDisplays.put(displayId, activityDisplay);
+ activityDisplay = new ActivityDisplay(this, displayId);
+ attachDisplay(activityDisplay);
calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
mWindowManager.onDisplayAdded(displayId);
return activityDisplay;
}
+ @VisibleForTesting
+ void attachDisplay(ActivityDisplay display) {
+ mActivityDisplays.put(display.mDisplayId, display);
+ }
+
private void calculateDefaultMinimalSizeOfResizeableTasks(ActivityDisplay display) {
mDefaultMinSizeOfResizeableTask =
mService.mContext.getResources().getDimensionPixelSize(
@@ -4104,7 +4119,7 @@
// 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.
- moveTasksToFullscreenStackLocked(stack.getStackId(), true /* onTop */);
+ moveTasksToFullscreenStackLocked(stack, true /* onTop */);
}
}
@@ -4166,7 +4181,7 @@
if (display.mAllSleepTokens.isEmpty()) {
return;
}
- for (SleepTokenImpl token : display.mAllSleepTokens) {
+ for (SleepToken token : display.mAllSleepTokens) {
mSleepTokens.remove(token);
}
display.mAllSleepTokens.clear();
@@ -4182,7 +4197,7 @@
info.displayId = displayId;
info.stackId = stack.mStackId;
info.userId = stack.mCurrentUser;
- info.visible = stack.shouldBeVisible(null) == STACK_VISIBLE;
+ info.visible = stack.shouldBeVisible(null);
// A stack might be not attached to a display.
info.position = display != null
? display.mStacks.indexOf(stack)
@@ -4289,7 +4304,11 @@
// Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
// we need to move it to top of fullscreen stack, otherwise it will be covered.
- moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, actualStackId == DOCKED_STACK_ID);
+ final ActivityStack dockedStack = getStack(DOCKED_STACK_ID);
+ if (dockedStack != null) {
+ moveTasksToFullscreenStackLocked(dockedStack,
+ actualStackId == dockedStack.getStackId());
+ }
} else if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
&& !topActivity.noDisplay) {
final String packageName = topActivity.appInfo.packageName;
@@ -4494,133 +4513,6 @@
}
}
- // TODO: Move to its own file.
- /** Exactly one of these classes per Display in the system. Capable of holding zero or more
- * attached {@link ActivityStack}s */
- class ActivityDisplay extends ConfigurationContainer {
- /** Actual Display this object tracks. */
- int mDisplayId;
- Display mDisplay;
-
- /** All of the stacks on this display. Order matters, topmost stack is in front of all other
- * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
- final ArrayList<ActivityStack> mStacks = new ArrayList<>();
-
- /** Array of all UIDs that are present on the display. */
- private IntArray mDisplayAccessUIDs = new IntArray();
-
- /** All tokens used to put activities on this stack to sleep (including mOffToken) */
- final ArrayList<SleepTokenImpl> mAllSleepTokens = new ArrayList<>();
- /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */
- SleepToken mOffToken;
-
- private boolean mSleeping;
-
- @VisibleForTesting
- ActivityDisplay() {
- mActivityDisplays.put(mDisplayId, this);
- }
-
- // After instantiation, check that mDisplay is not null before using this. The alternative
- // is for this to throw an exception if mDisplayManager.getDisplay() returns null.
- ActivityDisplay(int displayId) {
- final Display display = mDisplayManager.getDisplay(displayId);
- if (display == null) {
- return;
- }
- init(display);
- }
-
- void init(Display display) {
- mDisplay = display;
- mDisplayId = display.getDisplayId();
- }
-
- void attachStack(ActivityStack stack, int position) {
- if (DEBUG_STACK) Slog.v(TAG_STACK, "attachStack: attaching " + stack
- + " to displayId=" + mDisplayId + " position=" + position);
- mStacks.add(position, stack);
- mService.updateSleepIfNeededLocked();
- }
-
- void detachStack(ActivityStack stack) {
- if (DEBUG_STACK) Slog.v(TAG_STACK, "detachStack: detaching " + stack
- + " from displayId=" + mDisplayId);
- mStacks.remove(stack);
- mService.updateSleepIfNeededLocked();
- }
-
- @Override
- public String toString() {
- return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
- }
-
- @Override
- protected int getChildCount() {
- return mStacks.size();
- }
-
- @Override
- protected ConfigurationContainer getChildAt(int index) {
- return mStacks.get(index);
- }
-
- @Override
- protected ConfigurationContainer getParent() {
- return ActivityStackSupervisor.this;
- }
-
- boolean isPrivate() {
- return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
- }
-
- boolean isUidPresent(int uid) {
- for (ActivityStack stack : mStacks) {
- if (stack.isUidPresent(uid)) {
- return true;
- }
- }
- return false;
- }
-
- /** Update and get all UIDs that are present on the display and have access to it. */
- private IntArray getPresentUIDs() {
- mDisplayAccessUIDs.clear();
- for (ActivityStack stack : mStacks) {
- stack.getPresentUIDs(mDisplayAccessUIDs);
- }
- return mDisplayAccessUIDs;
- }
-
- boolean shouldDestroyContentOnRemove() {
- return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
- }
-
- boolean shouldSleep() {
- return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
- && (mService.mRunningVoice == null);
- }
-
- boolean isSleeping() {
- return mSleeping;
- }
-
- void setIsSleeping(boolean asleep) {
- mSleeping = asleep;
- }
-
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
- super.writeToProto(proto, ActivityDisplayProto.CONFIGURATION_CONTAINER);
- proto.write(ID, mDisplayId);
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.writeToProto(proto, STACKS);
- }
- proto.end(token);
- }
- }
-
ActivityStack findStackBehind(ActivityStack stack) {
// TODO(multi-display): We are only looking for stacks on the default display.
final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
@@ -4756,8 +4648,7 @@
for (int j = display.mStacks.size() - 1; j >= 0; j--) {
final ActivityStack stack = display.mStacks.get(j);
// Get top activity from a visible stack and add it to the list.
- if (stack.shouldBeVisible(null /* starting */)
- == ActivityStack.STACK_VISIBLE) {
+ if (stack.shouldBeVisible(null /* starting */)) {
final ActivityRecord top = stack.topActivity();
if (top != null) {
if (stack == mFocusedStack) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index fab4d0d..1a2b46c 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -39,7 +39,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
@@ -78,7 +77,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.ANIMATE;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
@@ -1241,7 +1239,7 @@
mOptions);
}
} else {
- mTargetStack.addRecentActivityLocked(mStartActivity);
+ mSupervisor.addRecentActivity(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
@@ -2107,7 +2105,8 @@
}
if (stack == null) {
// We first try to put the task in the first dynamic stack on home display.
- final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
+ final ArrayList<ActivityStack> homeDisplayStacks =
+ mSupervisor.getStacksOnDefaultDisplay();
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
stack = homeDisplayStacks.get(stackNdx);
if (isDynamicStack(stack.mStackId)) {
@@ -2245,8 +2244,7 @@
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
- if (dockedStack != null
- && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
+ if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
} else {
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index e03c530..7101fc4 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -342,8 +342,12 @@
// show on top of the lock screen. In this can we want to dismiss the docked
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
- mStackSupervisor.moveTasksToFullscreenStackLocked(DOCKED_STACK_ID,
- mStackSupervisor.mFocusedStack.getStackId() == DOCKED_STACK_ID);
+ final ActivityStack stack = mStackSupervisor.getStack(DOCKED_STACK_ID);
+ if (stack == null) {
+ return;
+ }
+ mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
+ mStackSupervisor.mFocusedStack == stack);
}
}
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index a601ee1..33f5664 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -32,9 +32,9 @@
class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
implements PinnedStackWindowListener {
- PinnedActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId,
- ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) {
- super(display, stackId, supervisor, recentTasks, onTop);
+ PinnedActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
+ boolean onTop) {
+ super(display, stackId, supervisor, onTop);
}
@Override
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 1da94da..b7b1f7c 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -225,9 +225,15 @@
/*@WindowConfiguration.ActivityType*/ int thisType = getActivityType();
/*@WindowConfiguration.ActivityType*/ int otherType = other.getActivityType();
- return thisType == otherType
- || thisType == ACTIVITY_TYPE_UNDEFINED
- || otherType == ACTIVITY_TYPE_UNDEFINED;
+ if (thisType == otherType) {
+ return true;
+ }
+ if (thisType == ACTIVITY_TYPE_ASSISTANT) {
+ // Assistant activities are only compatible with themselves...
+ return false;
+ }
+ // Otherwise we are compatible if us or other is not currently defined.
+ return thisType == ACTIVITY_TYPE_UNDEFINED || otherType == ACTIVITY_TYPE_UNDEFINED;
}
public void registerConfigurationChangeListener(ConfigurationContainerListener listener) {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 0cf1df8..6caa60b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.view.Display.DEFAULT_DISPLAY;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.any;
@@ -24,7 +25,6 @@
import org.mockito.invocation.InvocationOnMock;
-import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +32,7 @@
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
import android.os.HandlerThread;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
@@ -167,8 +168,11 @@
public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
super(service, looper);
+ mDisplayManager =
+ (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
mWindowManager = prepareMockWindowManager();
- mDisplay = new ActivityDisplay();
+ mDisplay = new ActivityDisplay(this, DEFAULT_DISPLAY);
+ attachDisplay(mDisplay);
}
// TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor
@@ -220,17 +224,15 @@
@Override
ActivityStack createStack(int stackId, ActivityDisplay display, boolean onTop) {
- final RecentTasks recents =
- new RecentTasks(mService, mService.mStackSupervisor);
if (stackId == PINNED_STACK_ID) {
- return new PinnedActivityStack(display, stackId, this, recents, onTop) {
+ return new PinnedActivityStack(display, stackId, this, onTop) {
@Override
Rect getDefaultPictureInPictureBounds(float aspectRatio) {
return new Rect(50, 50, 100, 100);
}
};
} else {
- return new TestActivityStack(display, stackId, this, recents, onTop);
+ return new TestActivityStack(display, stackId, this, onTop);
}
}
@@ -280,9 +282,9 @@
extends ActivityStack<T> implements ActivityStackReporter {
private int mOnActivityRemovedFromStackCount = 0;
private T mContainerController;
- TestActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId,
- ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) {
- super(display, stackId, supervisor, recentTasks, onTop);
+ TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
+ boolean onTop) {
+ super(display, stackId, supervisor, onTop);
}
@Override