diff options
Diffstat (limited to 'com/android/server/am/ActivityDisplay.java')
-rw-r--r-- | com/android/server/am/ActivityDisplay.java | 197 |
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); |