Loading services/core/java/com/android/server/am/ActivityDisplay.java +33 −13 Original line number Original line Diff line number Diff line Loading @@ -296,7 +296,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r, <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType, @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType, boolean onTop) { boolean onTop) { final int windowingMode = resolveWindowingMode(r, options, candidateTask, activityType); // First preference is the windowing mode in the activity options if set. int windowingMode = (options != null) ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED; // Validate that our desired windowingMode will work under the current conditions. // UNDEFINED windowing mode is a valid result and means that the new stack will inherit // it's display's windowing mode. windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType); return getOrCreateStack(windowingMode, activityType, onTop); return getOrCreateStack(windowingMode, activityType, onTop); } } Loading @@ -308,7 +314,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> * Creates a stack matching the input windowing mode and activity type on this display. * Creates a stack matching the input windowing mode and activity type on this display. * @param windowingMode The windowing mode the stack should be created in. If * @param windowingMode The windowing mode the stack should be created in. If * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will * be created in {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. * inherit it's parent's windowing mode. * @param activityType The activityType the stack should be created in. If * @param activityType The activityType the stack should be created in. If * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}. * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}. Loading Loading @@ -589,7 +595,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (!otherStack.inSplitScreenSecondaryWindowingMode()) { if (!otherStack.inSplitScreenSecondaryWindowingMode()) { continue; continue; } } otherStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN, false /* animate */, otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */, false /* showRecents */, false /* enteringSplitScreenMode */, false /* showRecents */, false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */); true /* deferEnsuringVisibility */); } } Loading Loading @@ -650,10 +656,14 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return false; return false; } } final int displayWindowingMode = getWindowingMode(); if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { return supportsSplitScreen return supportsSplitScreen && WindowConfiguration.supportSplitScreenWindowingMode(activityType); && WindowConfiguration.supportSplitScreenWindowingMode(activityType) // Freeform windows and split-screen windows don't mix well, so prevent // split windowing modes on freeform displays. && displayWindowingMode != WINDOWING_MODE_FREEFORM; } } if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) { if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) { Loading @@ -666,6 +676,16 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return true; return true; } } /** * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this * display with the provided parameters. * * @param r The ActivityRecord in question. * @param options Options to start with. * @param task The task within-which the activity would start. * @param activityType The type of activity to start. * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in. */ int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options, int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable TaskRecord task, int activityType) { @Nullable TaskRecord task, int activityType) { Loading @@ -687,7 +707,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> windowingMode = getWindowingMode(); windowingMode = getWindowingMode(); } } } } return validateWindowingMode(windowingMode, r, task, activityType); windowingMode = validateWindowingMode(windowingMode, r, task, activityType); return windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : WINDOWING_MODE_FULLSCREEN; } } /** /** Loading Loading @@ -724,10 +746,11 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> final boolean inSplitScreenMode = hasSplitScreenPrimaryStack(); final boolean inSplitScreenMode = hasSplitScreenPrimaryStack(); if (!inSplitScreenMode if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) { && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) { // Switch to fullscreen windowing mode if we are not in split-screen mode and we are // Switch to the display's windowing mode if we are not in split-screen mode and we are // trying to launch in split-screen secondary. // trying to launch in split-screen secondary. windowingMode = WINDOWING_MODE_FULLSCREEN; windowingMode = WINDOWING_MODE_UNDEFINED; } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_UNDEFINED) && supportsSplitScreen) { && supportsSplitScreen) { windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; } } Loading @@ -737,10 +760,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> supportsFreeform, supportsPip, activityType)) { supportsFreeform, supportsPip, activityType)) { return windowingMode; return windowingMode; } } // Try to use the display's windowing mode otherwise fallback to fullscreen. return WINDOWING_MODE_UNDEFINED; windowingMode = getWindowingMode(); return windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : WINDOWING_MODE_FULLSCREEN; } } /** /** Loading services/core/java/com/android/server/am/ActivityStack.java +58 −15 Original line number Original line Diff line number Diff line Loading @@ -347,6 +347,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** The attached Display's unique identifier, or -1 if detached */ /** The attached Display's unique identifier, or -1 if detached */ int mDisplayId; int mDisplayId; /** Stores the override windowing-mode from before a transient mode change (eg. split) */ private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED; private final SparseArray<Rect> mTmpBounds = new SparseArray<>(); private final SparseArray<Rect> mTmpBounds = new SparseArray<>(); private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>(); private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>(); private final Rect mTmpRect2 = new Rect(); private final Rect mTmpRect2 = new Rect(); Loading Loading @@ -531,16 +534,48 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */); false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */); } } /** * A transient windowing mode is one which activities enter into temporarily. Examples of this * are Split window modes and pip. Non-transient modes are modes that displays can adopt. * * @param windowingMode the windowingMode to test for transient-ness. * @return {@code true} if the windowing mode is transient, {@code false} otherwise. */ private static boolean isTransientWindowingMode(int windowingMode) { // TODO(b/114842032): add PIP if/when it uses mode transitions instead of task reparenting return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; } /** * Specialization of {@link #setWindowingMode(int)} for this subclass. * * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending * on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the * previous non-transient mode if this stack is currently in a transient mode. * @param animate Can be used to prevent animation. * @param showRecents Controls whether recents is shown on the other side of a split while * entering split mode. * @param enteringSplitScreenMode {@code true} if entering split mode. * @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when * many operations (which can effect visibility) are being performed in bulk. */ void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) { boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) { final boolean creating = mWindowContainerController == null; final boolean creating = mWindowContainerController == null; final int currentMode = getWindowingMode(); final int currentMode = getWindowingMode(); final int currentOverrideMode = getOverrideWindowingMode(); final ActivityDisplay display = getDisplay(); final ActivityDisplay display = getDisplay(); final TaskRecord topTask = topTask(); final TaskRecord topTask = topTask(); final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack(); final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack(); mTmpOptions.setLaunchWindowingMode(preferredWindowingMode); int windowingMode = preferredWindowingMode; int windowingMode = preferredWindowingMode; if (preferredWindowingMode == WINDOWING_MODE_UNDEFINED && isTransientWindowingMode(currentMode)) { // Leaving a transient mode. Interpret UNDEFINED as "restore" windowingMode = mRestoreOverrideWindowingMode; } mTmpOptions.setLaunchWindowingMode(windowingMode); // Need to make sure windowing mode is supported. If we in the process of creating the stack // Need to make sure windowing mode is supported. If we in the process of creating the stack // no need to resolve the windowing mode again as it is already resolved to the right mode. // no need to resolve the windowing mode again as it is already resolved to the right mode. if (!creating) { if (!creating) { Loading @@ -550,8 +585,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (splitScreenStack == this if (splitScreenStack == this && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { // Resolution to split-screen secondary for the primary split-screen stack means // Resolution to split-screen secondary for the primary split-screen stack means // we want to go fullscreen. // we want to leave split-screen mode. windowingMode = WINDOWING_MODE_FULLSCREEN; windowingMode = mRestoreOverrideWindowingMode; } } final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack(); final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack(); Loading @@ -570,21 +605,33 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // doesn't support split-screen mode, go ahead an dismiss split-screen and display a // doesn't support split-screen mode, go ahead an dismiss split-screen and display a // warning toast about it. // warning toast about it. mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack(); mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack(); display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN, display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */, false /* showRecents */, false /* animate */, false /* showRecents */, false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */); false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */); } } } } if (currentMode == windowingMode) { if (currentMode == windowingMode) { // You are already in the window mode silly... // You are already in the window mode, so we can skip most of the work below. However, // it's possible that we have inherited the current windowing mode from a parent. So, // fulfill this method's contract by setting the override mode directly. getOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode); return; return; } } final WindowManagerService wm = mService.mWindowManager; final WindowManagerService wm = mService.mWindowManager; final ActivityRecord topActivity = getTopActivity(); final ActivityRecord topActivity = getTopActivity(); if (sendNonResizeableNotification && windowingMode != WINDOWING_MODE_FULLSCREEN // For now, assume that the Stack's windowing mode is what will actually be used // by it's activities. In the future, there may be situations where this doesn't // happen; so at that point, this message will need to handle that. int likelyResolvedMode = windowingMode; if (windowingMode == WINDOWING_MODE_UNDEFINED) { final ConfigurationContainer parent = getParent(); likelyResolvedMode = parent != null ? parent.getWindowingMode() : WINDOWING_MODE_FULLSCREEN; } if (sendNonResizeableNotification && likelyResolvedMode != WINDOWING_MODE_FULLSCREEN && topActivity != null && topActivity.isNonResizableOrForcedResizable() && topActivity != null && topActivity.isNonResizableOrForcedResizable() && !topActivity.noDisplay) { && !topActivity.noDisplay) { // Inform the user that they are starting an app that may not work correctly in // Inform the user that they are starting an app that may not work correctly in Loading Loading @@ -625,6 +672,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai + " while there is already one isn't currently supported"); + " while there is already one isn't currently supported"); //return; //return; } } if (isTransientWindowingMode(windowingMode) && !isTransientWindowingMode(currentMode)) { mRestoreOverrideWindowingMode = currentOverrideMode; } mTmpRect2.setEmpty(); mTmpRect2.setEmpty(); if (windowingMode != WINDOWING_MODE_FULLSCREEN) { if (windowingMode != WINDOWING_MODE_FULLSCREEN) { Loading Loading @@ -674,13 +724,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // display, so they should be considered compatible. // display, so they should be considered compatible. activityType = ACTIVITY_TYPE_STANDARD; activityType = ACTIVITY_TYPE_STANDARD; } } final ActivityDisplay display = getDisplay(); if (display != null && activityType == ACTIVITY_TYPE_STANDARD && windowingMode == WINDOWING_MODE_UNDEFINED) { // Standard activity types will mostly take on the windowing mode of the display if one // isn't specified, so look-up a compatible stack based on the display's windowing mode. windowingMode = display.getWindowingMode(); } return super.isCompatible(windowingMode, activityType); return super.isCompatible(windowingMode, activityType); } } Loading Loading @@ -1085,7 +1128,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * behind the home stack. Exit split screen in this case. * behind the home stack. Exit split screen in this case. */ */ if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { setWindowingMode(WINDOWING_MODE_FULLSCREEN); setWindowingMode(WINDOWING_MODE_UNDEFINED); } } getDisplay().positionChildAtBottom(this); getDisplay().positionChildAtBottom(this); Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +1 −2 Original line number Original line Diff line number Diff line Loading @@ -2828,8 +2828,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (!otherStack.inSplitScreenSecondaryWindowingMode()) { if (!otherStack.inSplitScreenSecondaryWindowingMode()) { continue; continue; } } resizeStackLocked(otherStack, null, null, null, PRESERVE_WINDOWS, otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED); true /* allowResizeInDockedMode */, DEFER_RESUME); } } // Also disable docked stack resizing since we have manually adjusted the // Also disable docked stack resizing since we have manually adjusted the Loading services/core/java/com/android/server/am/ActivityTaskManagerService.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -3338,7 +3338,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } } } stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); stack.setWindowingMode(WINDOWING_MODE_UNDEFINED); } } } finally { } finally { Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident); Loading services/core/java/com/android/server/wm/ConfigurationContainer.java +7 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.WindowConfiguration.windowingModeToString; import static android.app.WindowConfiguration.windowingModeToString; import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGURATION; Loading Loading @@ -295,6 +296,10 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { return mFullConfiguration.windowConfiguration.getWindowingMode(); return mFullConfiguration.windowConfiguration.getWindowingMode(); } } public int getOverrideWindowingMode() { return mOverrideConfiguration.windowConfiguration.getWindowingMode(); } /** Sets the windowing mode for the configuration container. */ /** Sets the windowing mode for the configuration container. */ public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) { public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) { mTmpConfig.setTo(getOverrideConfiguration()); mTmpConfig.setTo(getOverrideConfiguration()); Loading Loading @@ -513,7 +518,8 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { final String childPrefix = prefix + " "; final String childPrefix = prefix + " "; pw.println(getName() pw.println(getName() + " type=" + activityTypeToString(getActivityType()) + " type=" + activityTypeToString(getActivityType()) + " mode=" + windowingModeToString(getWindowingMode())); + " mode=" + windowingModeToString(getWindowingMode()) + " override-mode=" + windowingModeToString(getOverrideWindowingMode())); for (int i = getChildCount() - 1; i >= 0; --i) { for (int i = getChildCount() - 1; i >= 0; --i) { final E cc = getChildAt(i); final E cc = getChildAt(i); pw.print(childPrefix + "#" + i + " "); pw.print(childPrefix + "#" + i + " "); Loading Loading
services/core/java/com/android/server/am/ActivityDisplay.java +33 −13 Original line number Original line Diff line number Diff line Loading @@ -296,7 +296,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r, <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType, @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType, boolean onTop) { boolean onTop) { final int windowingMode = resolveWindowingMode(r, options, candidateTask, activityType); // First preference is the windowing mode in the activity options if set. int windowingMode = (options != null) ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED; // Validate that our desired windowingMode will work under the current conditions. // UNDEFINED windowing mode is a valid result and means that the new stack will inherit // it's display's windowing mode. windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType); return getOrCreateStack(windowingMode, activityType, onTop); return getOrCreateStack(windowingMode, activityType, onTop); } } Loading @@ -308,7 +314,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> * Creates a stack matching the input windowing mode and activity type on this display. * Creates a stack matching the input windowing mode and activity type on this display. * @param windowingMode The windowing mode the stack should be created in. If * @param windowingMode The windowing mode the stack should be created in. If * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will * be created in {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. * inherit it's parent's windowing mode. * @param activityType The activityType the stack should be created in. If * @param activityType The activityType the stack should be created in. If * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}. * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}. Loading Loading @@ -589,7 +595,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (!otherStack.inSplitScreenSecondaryWindowingMode()) { if (!otherStack.inSplitScreenSecondaryWindowingMode()) { continue; continue; } } otherStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN, false /* animate */, otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */, false /* showRecents */, false /* enteringSplitScreenMode */, false /* showRecents */, false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */); true /* deferEnsuringVisibility */); } } Loading Loading @@ -650,10 +656,14 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return false; return false; } } final int displayWindowingMode = getWindowingMode(); if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { return supportsSplitScreen return supportsSplitScreen && WindowConfiguration.supportSplitScreenWindowingMode(activityType); && WindowConfiguration.supportSplitScreenWindowingMode(activityType) // Freeform windows and split-screen windows don't mix well, so prevent // split windowing modes on freeform displays. && displayWindowingMode != WINDOWING_MODE_FREEFORM; } } if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) { if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) { Loading @@ -666,6 +676,16 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return true; return true; } } /** * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this * display with the provided parameters. * * @param r The ActivityRecord in question. * @param options Options to start with. * @param task The task within-which the activity would start. * @param activityType The type of activity to start. * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in. */ int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options, int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable TaskRecord task, int activityType) { @Nullable TaskRecord task, int activityType) { Loading @@ -687,7 +707,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> windowingMode = getWindowingMode(); windowingMode = getWindowingMode(); } } } } return validateWindowingMode(windowingMode, r, task, activityType); windowingMode = validateWindowingMode(windowingMode, r, task, activityType); return windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : WINDOWING_MODE_FULLSCREEN; } } /** /** Loading Loading @@ -724,10 +746,11 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> final boolean inSplitScreenMode = hasSplitScreenPrimaryStack(); final boolean inSplitScreenMode = hasSplitScreenPrimaryStack(); if (!inSplitScreenMode if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) { && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) { // Switch to fullscreen windowing mode if we are not in split-screen mode and we are // Switch to the display's windowing mode if we are not in split-screen mode and we are // trying to launch in split-screen secondary. // trying to launch in split-screen secondary. windowingMode = WINDOWING_MODE_FULLSCREEN; windowingMode = WINDOWING_MODE_UNDEFINED; } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_UNDEFINED) && supportsSplitScreen) { && supportsSplitScreen) { windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; } } Loading @@ -737,10 +760,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> supportsFreeform, supportsPip, activityType)) { supportsFreeform, supportsPip, activityType)) { return windowingMode; return windowingMode; } } // Try to use the display's windowing mode otherwise fallback to fullscreen. return WINDOWING_MODE_UNDEFINED; windowingMode = getWindowingMode(); return windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : WINDOWING_MODE_FULLSCREEN; } } /** /** Loading
services/core/java/com/android/server/am/ActivityStack.java +58 −15 Original line number Original line Diff line number Diff line Loading @@ -347,6 +347,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** The attached Display's unique identifier, or -1 if detached */ /** The attached Display's unique identifier, or -1 if detached */ int mDisplayId; int mDisplayId; /** Stores the override windowing-mode from before a transient mode change (eg. split) */ private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED; private final SparseArray<Rect> mTmpBounds = new SparseArray<>(); private final SparseArray<Rect> mTmpBounds = new SparseArray<>(); private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>(); private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>(); private final Rect mTmpRect2 = new Rect(); private final Rect mTmpRect2 = new Rect(); Loading Loading @@ -531,16 +534,48 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */); false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */); } } /** * A transient windowing mode is one which activities enter into temporarily. Examples of this * are Split window modes and pip. Non-transient modes are modes that displays can adopt. * * @param windowingMode the windowingMode to test for transient-ness. * @return {@code true} if the windowing mode is transient, {@code false} otherwise. */ private static boolean isTransientWindowingMode(int windowingMode) { // TODO(b/114842032): add PIP if/when it uses mode transitions instead of task reparenting return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; } /** * Specialization of {@link #setWindowingMode(int)} for this subclass. * * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending * on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the * previous non-transient mode if this stack is currently in a transient mode. * @param animate Can be used to prevent animation. * @param showRecents Controls whether recents is shown on the other side of a split while * entering split mode. * @param enteringSplitScreenMode {@code true} if entering split mode. * @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when * many operations (which can effect visibility) are being performed in bulk. */ void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) { boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) { final boolean creating = mWindowContainerController == null; final boolean creating = mWindowContainerController == null; final int currentMode = getWindowingMode(); final int currentMode = getWindowingMode(); final int currentOverrideMode = getOverrideWindowingMode(); final ActivityDisplay display = getDisplay(); final ActivityDisplay display = getDisplay(); final TaskRecord topTask = topTask(); final TaskRecord topTask = topTask(); final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack(); final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack(); mTmpOptions.setLaunchWindowingMode(preferredWindowingMode); int windowingMode = preferredWindowingMode; int windowingMode = preferredWindowingMode; if (preferredWindowingMode == WINDOWING_MODE_UNDEFINED && isTransientWindowingMode(currentMode)) { // Leaving a transient mode. Interpret UNDEFINED as "restore" windowingMode = mRestoreOverrideWindowingMode; } mTmpOptions.setLaunchWindowingMode(windowingMode); // Need to make sure windowing mode is supported. If we in the process of creating the stack // Need to make sure windowing mode is supported. If we in the process of creating the stack // no need to resolve the windowing mode again as it is already resolved to the right mode. // no need to resolve the windowing mode again as it is already resolved to the right mode. if (!creating) { if (!creating) { Loading @@ -550,8 +585,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (splitScreenStack == this if (splitScreenStack == this && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { // Resolution to split-screen secondary for the primary split-screen stack means // Resolution to split-screen secondary for the primary split-screen stack means // we want to go fullscreen. // we want to leave split-screen mode. windowingMode = WINDOWING_MODE_FULLSCREEN; windowingMode = mRestoreOverrideWindowingMode; } } final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack(); final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack(); Loading @@ -570,21 +605,33 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // doesn't support split-screen mode, go ahead an dismiss split-screen and display a // doesn't support split-screen mode, go ahead an dismiss split-screen and display a // warning toast about it. // warning toast about it. mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack(); mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack(); display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN, display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */, false /* showRecents */, false /* animate */, false /* showRecents */, false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */); false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */); } } } } if (currentMode == windowingMode) { if (currentMode == windowingMode) { // You are already in the window mode silly... // You are already in the window mode, so we can skip most of the work below. However, // it's possible that we have inherited the current windowing mode from a parent. So, // fulfill this method's contract by setting the override mode directly. getOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode); return; return; } } final WindowManagerService wm = mService.mWindowManager; final WindowManagerService wm = mService.mWindowManager; final ActivityRecord topActivity = getTopActivity(); final ActivityRecord topActivity = getTopActivity(); if (sendNonResizeableNotification && windowingMode != WINDOWING_MODE_FULLSCREEN // For now, assume that the Stack's windowing mode is what will actually be used // by it's activities. In the future, there may be situations where this doesn't // happen; so at that point, this message will need to handle that. int likelyResolvedMode = windowingMode; if (windowingMode == WINDOWING_MODE_UNDEFINED) { final ConfigurationContainer parent = getParent(); likelyResolvedMode = parent != null ? parent.getWindowingMode() : WINDOWING_MODE_FULLSCREEN; } if (sendNonResizeableNotification && likelyResolvedMode != WINDOWING_MODE_FULLSCREEN && topActivity != null && topActivity.isNonResizableOrForcedResizable() && topActivity != null && topActivity.isNonResizableOrForcedResizable() && !topActivity.noDisplay) { && !topActivity.noDisplay) { // Inform the user that they are starting an app that may not work correctly in // Inform the user that they are starting an app that may not work correctly in Loading Loading @@ -625,6 +672,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai + " while there is already one isn't currently supported"); + " while there is already one isn't currently supported"); //return; //return; } } if (isTransientWindowingMode(windowingMode) && !isTransientWindowingMode(currentMode)) { mRestoreOverrideWindowingMode = currentOverrideMode; } mTmpRect2.setEmpty(); mTmpRect2.setEmpty(); if (windowingMode != WINDOWING_MODE_FULLSCREEN) { if (windowingMode != WINDOWING_MODE_FULLSCREEN) { Loading Loading @@ -674,13 +724,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // display, so they should be considered compatible. // display, so they should be considered compatible. activityType = ACTIVITY_TYPE_STANDARD; activityType = ACTIVITY_TYPE_STANDARD; } } final ActivityDisplay display = getDisplay(); if (display != null && activityType == ACTIVITY_TYPE_STANDARD && windowingMode == WINDOWING_MODE_UNDEFINED) { // Standard activity types will mostly take on the windowing mode of the display if one // isn't specified, so look-up a compatible stack based on the display's windowing mode. windowingMode = display.getWindowingMode(); } return super.isCompatible(windowingMode, activityType); return super.isCompatible(windowingMode, activityType); } } Loading Loading @@ -1085,7 +1128,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * behind the home stack. Exit split screen in this case. * behind the home stack. Exit split screen in this case. */ */ if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { setWindowingMode(WINDOWING_MODE_FULLSCREEN); setWindowingMode(WINDOWING_MODE_UNDEFINED); } } getDisplay().positionChildAtBottom(this); getDisplay().positionChildAtBottom(this); Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +1 −2 Original line number Original line Diff line number Diff line Loading @@ -2828,8 +2828,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (!otherStack.inSplitScreenSecondaryWindowingMode()) { if (!otherStack.inSplitScreenSecondaryWindowingMode()) { continue; continue; } } resizeStackLocked(otherStack, null, null, null, PRESERVE_WINDOWS, otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED); true /* allowResizeInDockedMode */, DEFER_RESUME); } } // Also disable docked stack resizing since we have manually adjusted the // Also disable docked stack resizing since we have manually adjusted the Loading
services/core/java/com/android/server/am/ActivityTaskManagerService.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -3338,7 +3338,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } } } stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); stack.setWindowingMode(WINDOWING_MODE_UNDEFINED); } } } finally { } finally { Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident); Loading
services/core/java/com/android/server/wm/ConfigurationContainer.java +7 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.WindowConfiguration.windowingModeToString; import static android.app.WindowConfiguration.windowingModeToString; import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGURATION; import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGURATION; Loading Loading @@ -295,6 +296,10 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { return mFullConfiguration.windowConfiguration.getWindowingMode(); return mFullConfiguration.windowConfiguration.getWindowingMode(); } } public int getOverrideWindowingMode() { return mOverrideConfiguration.windowConfiguration.getWindowingMode(); } /** Sets the windowing mode for the configuration container. */ /** Sets the windowing mode for the configuration container. */ public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) { public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) { mTmpConfig.setTo(getOverrideConfiguration()); mTmpConfig.setTo(getOverrideConfiguration()); Loading Loading @@ -513,7 +518,8 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { final String childPrefix = prefix + " "; final String childPrefix = prefix + " "; pw.println(getName() pw.println(getName() + " type=" + activityTypeToString(getActivityType()) + " type=" + activityTypeToString(getActivityType()) + " mode=" + windowingModeToString(getWindowingMode())); + " mode=" + windowingModeToString(getWindowingMode()) + " override-mode=" + windowingModeToString(getOverrideWindowingMode())); for (int i = getChildCount() - 1; i >= 0; --i) { for (int i = getChildCount() - 1; i >= 0; --i) { final E cc = getChildAt(i); final E cc = getChildAt(i); pw.print(childPrefix + "#" + i + " "); pw.print(childPrefix + "#" + i + " "); Loading