summaryrefslogtreecommitdiff
path: root/com/android/server/am/ActivityDisplay.java
diff options
context:
space:
mode:
Diffstat (limited to 'com/android/server/am/ActivityDisplay.java')
-rw-r--r--com/android/server/am/ActivityDisplay.java197
1 files changed, 149 insertions, 48 deletions
diff --git a/com/android/server/am/ActivityDisplay.java b/com/android/server/am/ActivityDisplay.java
index 8bcbfbef..089db871 100644
--- a/com/android/server/am/ActivityDisplay.java
+++ b/com/android/server/am/ActivityDisplay.java
@@ -16,12 +16,11 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.getStackIdForWindowingMode;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
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_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -48,13 +47,14 @@ import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.ConfigurationContainer;
+import java.io.PrintWriter;
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 {
+class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
@@ -68,7 +68,7 @@ class ActivityDisplay extends ConfigurationContainer {
/** 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<>();
+ private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
/** Array of all UIDs that are present on the display. */
private IntArray mDisplayAccessUIDs = new IntArray();
@@ -80,6 +80,13 @@ class ActivityDisplay extends ConfigurationContainer {
private boolean mSleeping;
+ // 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;
+ private ActivityStack mRecentsStack = null;
+ private ActivityStack mPinnedStack = null;
+ private ActivityStack mSplitScreenPrimaryStack = null;
+
ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
mSupervisor = supervisor;
mDisplayId = displayId;
@@ -98,6 +105,7 @@ class ActivityDisplay extends ConfigurationContainer {
}
if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
+ " to displayId=" + mDisplayId + " position=" + position);
+ addStackReferenceIfNeeded(stack);
positionChildAt(stack, position);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -106,6 +114,7 @@ class ActivityDisplay extends ConfigurationContainer {
if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
+ removeStackReferenceIfNeeded(stack);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -150,9 +159,19 @@ class ActivityDisplay extends ConfigurationContainer {
* @see ConfigurationContainer#isCompatible(int, int)
*/
<T extends ActivityStack> T getStack(int windowingMode, int activityType) {
+ if (activityType == ACTIVITY_TYPE_HOME) {
+ return (T) mHomeStack;
+ } else if (activityType == ACTIVITY_TYPE_RECENTS) {
+ return (T) mRecentsStack;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ return (T) mPinnedStack;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ return (T) mSplitScreenPrimaryStack;
+ }
+
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
- // TODO: Should undefined windowing and activity type be compatible with standard type?
if (stack.isCompatible(windowingMode, activityType)) {
return (T) stack;
}
@@ -160,15 +179,28 @@ class ActivityDisplay extends ConfigurationContainer {
return null;
}
+ private boolean alwaysCreateStack(int windowingMode, int activityType) {
+ // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
+ // modes so that we can manage visual ordering and return types correctly.
+ return activityType == ACTIVITY_TYPE_STANDARD
+ && (windowingMode == WINDOWING_MODE_FULLSCREEN
+ || windowingMode == WINDOWING_MODE_FREEFORM
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ }
+
/**
+ * Returns an existing stack compatible with the windowing mode and activity type or creates one
+ * if a compatible stack doesn't exist.
* @see #getStack(int, int)
* @see #createStack(int, int, boolean)
*/
<T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
boolean onTop) {
- T stack = getStack(windowingMode, activityType);
- if (stack != null) {
- return stack;
+ if (!alwaysCreateStack(windowingMode, activityType)) {
+ T stack = getStack(windowingMode, activityType);
+ if (stack != null) {
+ return stack;
+ }
}
return createStack(windowingMode, activityType, onTop);
}
@@ -213,39 +245,16 @@ class ActivityDisplay extends ConfigurationContainer {
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
// TODO: Should be okay to have stacks with with undefined windowing mode long term, but
// have to set them to something for now due to logic that depending on them.
- windowingMode = WINDOWING_MODE_FULLSCREEN;
- }
-
- final boolean inSplitScreenMode = hasSplitScreenStack();
- if (!inSplitScreenMode
- && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
- // Switch to fullscreen windowing mode if we are not in split-screen mode and we are
- // trying to launch in split-screen secondary.
- windowingMode = WINDOWING_MODE_FULLSCREEN;
- } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
- && WindowConfiguration.supportSplitScreenWindowingMode(
- windowingMode, activityType)) {
- windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
- }
-
- int stackId = INVALID_STACK_ID;
- if (mDisplayId == DEFAULT_DISPLAY && (activityType == ACTIVITY_TYPE_STANDARD
- || activityType == ACTIVITY_TYPE_UNDEFINED)) {
- // TODO: Will be removed once we are no longer using static stack ids.
- stackId = getStackIdForWindowingMode(windowingMode);
- if (stackId == INVALID_STACK_ID) {
- // Whatever...put in fullscreen stack for now.
- stackId = FULLSCREEN_WORKSPACE_STACK_ID;
- }
- final T stack = getStack(stackId);
- if (stack != null) {
- return stack;
+ windowingMode = getWindowingMode(); // Put in current display's windowing mode
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ // Else fullscreen for now...
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
}
}
- if (stackId == INVALID_STACK_ID) {
- stackId = mSupervisor.getNextStackId();
- }
+ windowingMode = updateWindowingModeForSplitScreenIfNeeded(windowingMode, activityType);
+
+ final int stackId = mSupervisor.getNextStackId();
final T stack = createStackUnchecked(windowingMode, activityType, stackId, onTop);
@@ -291,7 +300,7 @@ class ActivityDisplay extends ConfigurationContainer {
if (stack.getWindowingMode() != windowingMode) {
continue;
}
- mSupervisor.removeStackLocked(stack.mStackId);
+ mSupervisor.removeStack(stack);
}
}
}
@@ -306,12 +315,63 @@ class ActivityDisplay extends ConfigurationContainer {
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (stack.getActivityType() == activityType) {
- mSupervisor.removeStackLocked(stack.mStackId);
+ mSupervisor.removeStack(stack);
}
}
}
}
+ void onStackWindowingModeChanged(ActivityStack stack) {
+ removeStackReferenceIfNeeded(stack);
+ addStackReferenceIfNeeded(stack);
+ }
+
+ private void addStackReferenceIfNeeded(ActivityStack stack) {
+ final int activityType = stack.getActivityType();
+ final int windowingMode = stack.getWindowingMode();
+
+ if (activityType == ACTIVITY_TYPE_HOME) {
+ if (mHomeStack != null && mHomeStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+ + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+ }
+ mHomeStack = stack;
+ } else if (activityType == ACTIVITY_TYPE_RECENTS) {
+ if (mRecentsStack != null && mRecentsStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
+ + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
+ }
+ mRecentsStack = stack;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ if (mPinnedStack != null && mPinnedStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
+ + mPinnedStack + " already exist on display=" + this
+ + " stack=" + stack);
+ }
+ mPinnedStack = stack;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded:"
+ + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ mSplitScreenPrimaryStack = stack;
+ }
+ }
+
+ private void removeStackReferenceIfNeeded(ActivityStack stack) {
+ if (stack == mHomeStack) {
+ mHomeStack = null;
+ } else if (stack == mRecentsStack) {
+ mRecentsStack = null;
+ } else if (stack == mPinnedStack) {
+ mPinnedStack = null;
+ } else if (stack == mSplitScreenPrimaryStack) {
+ mSplitScreenPrimaryStack = null;
+ }
+ }
+
/** Returns the top visible stack activity type that isn't in the exclude windowing mode. */
int getTopVisibleStackActivityType(int excludeWindowingMode) {
for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -326,20 +386,57 @@ class ActivityDisplay extends ConfigurationContainer {
return ACTIVITY_TYPE_UNDEFINED;
}
- ActivityStack getSplitScreenStack() {
- return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ /**
+ * Get the topmost stack on the display. It may be different from focused stack, because
+ * focus may be on another display.
+ */
+ ActivityStack getTopStack() {
+ return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
+ }
+
+ boolean isTopStack(ActivityStack stack) {
+ return stack == getTopStack();
+ }
+
+ int getIndexOf(ActivityStack stack) {
+ return mStacks.indexOf(stack);
+ }
+
+ void onLockTaskPackagesUpdated() {
+ for (int i = mStacks.size() - 1; i >= 0; --i) {
+ mStacks.get(i).onLockTaskPackagesUpdated();
+ }
+ }
+
+ ActivityStack getSplitScreenPrimaryStack() {
+ return mSplitScreenPrimaryStack;
}
- boolean hasSplitScreenStack() {
- return getSplitScreenStack() != null;
+ boolean hasSplitScreenPrimaryStack() {
+ return mSplitScreenPrimaryStack != null;
}
PinnedActivityStack getPinnedStack() {
- return getStack(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ return (PinnedActivityStack) mPinnedStack;
}
boolean hasPinnedStack() {
- return getPinnedStack() != null;
+ return mPinnedStack != null;
+ }
+
+ int updateWindowingModeForSplitScreenIfNeeded(int windowingMode, int activityType) {
+ final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
+ if (!inSplitScreenMode
+ && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
+ // Switch to fullscreen windowing mode if we are not in split-screen mode and we are
+ // trying to launch in split-screen secondary.
+ return WINDOWING_MODE_FULLSCREEN;
+ } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
+ && WindowConfiguration.supportSplitScreenWindowingMode(
+ windowingMode, activityType)) {
+ return WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ }
+ return windowingMode;
}
@Override
@@ -353,7 +450,7 @@ class ActivityDisplay extends ConfigurationContainer {
}
@Override
- protected ConfigurationContainer getChildAt(int index) {
+ protected ActivityStack getChildAt(int index) {
return mStacks.get(index);
}
@@ -401,6 +498,10 @@ class ActivityDisplay extends ConfigurationContainer {
mSleeping = asleep;
}
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "displayId=" + mDisplayId + " mStacks=" + mStacks);
+ }
+
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER);