Home | History | Annotate | Download | only in am
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.server.am;
     18 
     19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
     20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
     21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
     22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
     23 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
     24 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
     25 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
     26 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
     27 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
     28 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
     29 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
     30 import static android.view.Display.DEFAULT_DISPLAY;
     31 import static android.view.Display.FLAG_PRIVATE;
     32 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
     33 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
     34 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
     35 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
     36 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
     37 import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
     38 import static com.android.server.am.ActivityDisplayProto.STACKS;
     39 import static com.android.server.am.ActivityDisplayProto.ID;
     40 
     41 import android.annotation.Nullable;
     42 import android.app.ActivityManagerInternal;
     43 import android.app.ActivityOptions;
     44 import android.app.WindowConfiguration;
     45 import android.graphics.Point;
     46 import android.util.IntArray;
     47 import android.util.Slog;
     48 import android.util.proto.ProtoOutputStream;
     49 import android.view.Display;
     50 import com.android.internal.annotations.VisibleForTesting;
     51 import com.android.server.wm.ConfigurationContainer;
     52 import com.android.server.wm.DisplayWindowController;
     53 
     54 import com.android.server.wm.WindowContainerListener;
     55 import java.io.PrintWriter;
     56 import java.util.ArrayList;
     57 
     58 /**
     59  * Exactly one of these classes per Display in the system. Capable of holding zero or more
     60  * attached {@link ActivityStack}s.
     61  */
     62 class ActivityDisplay extends ConfigurationContainer<ActivityStack>
     63         implements WindowContainerListener {
     64     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
     65     private static final String TAG_STACK = TAG + POSTFIX_STACK;
     66 
     67     static final int POSITION_TOP = Integer.MAX_VALUE;
     68     static final int POSITION_BOTTOM = Integer.MIN_VALUE;
     69 
     70 
     71     /**
     72      * Counter for next free stack ID to use for dynamic activity stacks. Unique across displays.
     73      */
     74     private static int sNextFreeStackId = 0;
     75 
     76     private ActivityStackSupervisor mSupervisor;
     77     /** Actual Display this object tracks. */
     78     int mDisplayId;
     79     Display mDisplay;
     80 
     81     /**
     82      * All of the stacks on this display. Order matters, topmost stack is in front of all other
     83      * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
     84      * changing the list should also call {@link #onStackOrderChanged()}.
     85      */
     86     private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
     87     private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
     88 
     89     /** Array of all UIDs that are present on the display. */
     90     private IntArray mDisplayAccessUIDs = new IntArray();
     91 
     92     /** All tokens used to put activities on this stack to sleep (including mOffToken) */
     93     final ArrayList<ActivityManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>();
     94     /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */
     95     ActivityManagerInternal.SleepToken mOffToken;
     96 
     97     private boolean mSleeping;
     98 
     99     // Cached reference to some special stacks we tend to get a lot so we don't need to loop
    100     // through the list to find them.
    101     private ActivityStack mHomeStack = null;
    102     private ActivityStack mRecentsStack = null;
    103     private ActivityStack mPinnedStack = null;
    104     private ActivityStack mSplitScreenPrimaryStack = null;
    105 
    106     // Used in updating the display size
    107     private Point mTmpDisplaySize = new Point();
    108 
    109     private DisplayWindowController mWindowContainerController;
    110 
    111     @VisibleForTesting
    112     ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
    113         this(supervisor, supervisor.mDisplayManager.getDisplay(displayId));
    114     }
    115 
    116     ActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
    117         mSupervisor = supervisor;
    118         mDisplayId = display.getDisplayId();
    119         mDisplay = display;
    120         mWindowContainerController = createWindowContainerController();
    121         updateBounds();
    122     }
    123 
    124     protected DisplayWindowController createWindowContainerController() {
    125         return new DisplayWindowController(mDisplay, this);
    126     }
    127 
    128     void updateBounds() {
    129         mDisplay.getSize(mTmpDisplaySize);
    130         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
    131     }
    132 
    133     void addChild(ActivityStack stack, int position) {
    134         if (position == POSITION_BOTTOM) {
    135             position = 0;
    136         } else if (position == POSITION_TOP) {
    137             position = mStacks.size();
    138         }
    139         if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
    140                 + " to displayId=" + mDisplayId + " position=" + position);
    141         addStackReferenceIfNeeded(stack);
    142         positionChildAt(stack, position);
    143         mSupervisor.mService.updateSleepIfNeededLocked();
    144     }
    145 
    146     void removeChild(ActivityStack stack) {
    147         if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
    148                 + " from displayId=" + mDisplayId);
    149         mStacks.remove(stack);
    150         removeStackReferenceIfNeeded(stack);
    151         mSupervisor.mService.updateSleepIfNeededLocked();
    152         onStackOrderChanged();
    153     }
    154 
    155     void positionChildAtTop(ActivityStack stack) {
    156         positionChildAt(stack, mStacks.size());
    157     }
    158 
    159     void positionChildAtBottom(ActivityStack stack) {
    160         positionChildAt(stack, 0);
    161     }
    162 
    163     private void positionChildAt(ActivityStack stack, int position) {
    164         // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
    165         //       the position internally, also update the logic here
    166         mStacks.remove(stack);
    167         final int insertPosition = getTopInsertPosition(stack, position);
    168         mStacks.add(insertPosition, stack);
    169         mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
    170                 insertPosition);
    171         onStackOrderChanged();
    172     }
    173 
    174     private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
    175         int position = mStacks.size();
    176         if (position > 0) {
    177             final ActivityStack topStack = mStacks.get(position - 1);
    178             if (topStack.getWindowConfiguration().isAlwaysOnTop() && topStack != stack) {
    179                 // If the top stack is always on top, we move this stack just below it.
    180                 position--;
    181             }
    182         }
    183         return Math.min(position, candidatePosition);
    184     }
    185 
    186     <T extends ActivityStack> T getStack(int stackId) {
    187         for (int i = mStacks.size() - 1; i >= 0; --i) {
    188             final ActivityStack stack = mStacks.get(i);
    189             if (stack.mStackId == stackId) {
    190                 return (T) stack;
    191             }
    192         }
    193         return null;
    194     }
    195 
    196     /**
    197      * @return the topmost stack on the display that is compatible with the input windowing mode and
    198      * activity type. {@code null} means no compatible stack on the display.
    199      * @see ConfigurationContainer#isCompatible(int, int)
    200      */
    201     <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
    202         if (activityType == ACTIVITY_TYPE_HOME) {
    203             return (T) mHomeStack;
    204         } else if (activityType == ACTIVITY_TYPE_RECENTS) {
    205             return (T) mRecentsStack;
    206         }
    207         if (windowingMode == WINDOWING_MODE_PINNED) {
    208             return (T) mPinnedStack;
    209         } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
    210             return (T) mSplitScreenPrimaryStack;
    211         }
    212 
    213         for (int i = mStacks.size() - 1; i >= 0; --i) {
    214             final ActivityStack stack = mStacks.get(i);
    215             if (stack.isCompatible(windowingMode, activityType)) {
    216                 return (T) stack;
    217             }
    218         }
    219         return null;
    220     }
    221 
    222     private boolean alwaysCreateStack(int windowingMode, int activityType) {
    223         // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
    224         // modes so that we can manage visual ordering and return types correctly.
    225         return activityType == ACTIVITY_TYPE_STANDARD
    226                 && (windowingMode == WINDOWING_MODE_FULLSCREEN
    227                 || windowingMode == WINDOWING_MODE_FREEFORM
    228                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
    229     }
    230 
    231     /**
    232      * Returns an existing stack compatible with the windowing mode and activity type or creates one
    233      * if a compatible stack doesn't exist.
    234      * @see #getStack(int, int)
    235      * @see #createStack(int, int, boolean)
    236      */
    237     <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
    238             boolean onTop) {
    239         if (!alwaysCreateStack(windowingMode, activityType)) {
    240             T stack = getStack(windowingMode, activityType);
    241             if (stack != null) {
    242                 return stack;
    243             }
    244         }
    245         return createStack(windowingMode, activityType, onTop);
    246     }
    247 
    248     /**
    249      * Returns an existing stack compatible with the input params or creates one
    250      * if a compatible stack doesn't exist.
    251      * @see #getOrCreateStack(int, int, boolean)
    252      */
    253     <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
    254             @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
    255             boolean onTop) {
    256         final int windowingMode = resolveWindowingMode(r, options, candidateTask, activityType);
    257         return getOrCreateStack(windowingMode, activityType, onTop);
    258     }
    259 
    260     private int getNextStackId() {
    261         return sNextFreeStackId++;
    262     }
    263 
    264     /**
    265      * Creates a stack matching the input windowing mode and activity type on this display.
    266      * @param windowingMode The windowing mode the stack should be created in. If
    267      *                      {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
    268      *                      be created in {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
    269      * @param activityType The activityType the stack should be created in. If
    270      *                     {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
    271      *                     be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
    272      * @param onTop If true the stack will be created at the top of the display, else at the bottom.
    273      * @return The newly created stack.
    274      */
    275     <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
    276 
    277         if (activityType == ACTIVITY_TYPE_UNDEFINED) {
    278             // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
    279             // anything else should be passing it in anyways...
    280             activityType = ACTIVITY_TYPE_STANDARD;
    281         }
    282 
    283         if (activityType != ACTIVITY_TYPE_STANDARD) {
    284             // For now there can be only one stack of a particular non-standard activity type on a
    285             // display. So, get that ignoring whatever windowing mode it is currently in.
    286             T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
    287             if (stack != null) {
    288                 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
    289                         + activityType + " already on display=" + this + ". Can't have multiple.");
    290             }
    291         }
    292 
    293         final ActivityManagerService service = mSupervisor.mService;
    294         if (!isWindowingModeSupported(windowingMode, service.mSupportsMultiWindow,
    295                 service.mSupportsSplitScreenMultiWindow, service.mSupportsFreeformWindowManagement,
    296                 service.mSupportsPictureInPicture, activityType)) {
    297             throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
    298                     + windowingMode);
    299         }
    300 
    301         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
    302             // TODO: Should be okay to have stacks with with undefined windowing mode long term, but
    303             // have to set them to something for now due to logic that depending on them.
    304             windowingMode = getWindowingMode(); // Put in current display's windowing mode
    305             if (windowingMode == WINDOWING_MODE_UNDEFINED) {
    306                 // Else fullscreen for now...
    307                 windowingMode = WINDOWING_MODE_FULLSCREEN;
    308             }
    309         }
    310 
    311         final int stackId = getNextStackId();
    312         return createStackUnchecked(windowingMode, activityType, stackId, onTop);
    313     }
    314 
    315     @VisibleForTesting
    316     <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
    317             int stackId, boolean onTop) {
    318         if (windowingMode == WINDOWING_MODE_PINNED) {
    319             return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop);
    320         }
    321         return (T) new ActivityStack(
    322                         this, stackId, mSupervisor, windowingMode, activityType, onTop);
    323     }
    324 
    325     /**
    326      * Removes stacks in the input windowing modes from the system if they are of activity type
    327      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
    328      */
    329     void removeStacksInWindowingModes(int... windowingModes) {
    330         if (windowingModes == null || windowingModes.length == 0) {
    331             return;
    332         }
    333 
    334         for (int j = windowingModes.length - 1 ; j >= 0; --j) {
    335             final int windowingMode = windowingModes[j];
    336             for (int i = mStacks.size() - 1; i >= 0; --i) {
    337                 final ActivityStack stack = mStacks.get(i);
    338                 if (!stack.isActivityTypeStandardOrUndefined()) {
    339                     continue;
    340                 }
    341                 if (stack.getWindowingMode() != windowingMode) {
    342                     continue;
    343                 }
    344                 mSupervisor.removeStack(stack);
    345             }
    346         }
    347     }
    348 
    349     void removeStacksWithActivityTypes(int... activityTypes) {
    350         if (activityTypes == null || activityTypes.length == 0) {
    351             return;
    352         }
    353 
    354         for (int j = activityTypes.length - 1 ; j >= 0; --j) {
    355             final int activityType = activityTypes[j];
    356             for (int i = mStacks.size() - 1; i >= 0; --i) {
    357                 final ActivityStack stack = mStacks.get(i);
    358                 if (stack.getActivityType() == activityType) {
    359                     mSupervisor.removeStack(stack);
    360                 }
    361             }
    362         }
    363     }
    364 
    365     void onStackWindowingModeChanged(ActivityStack stack) {
    366         removeStackReferenceIfNeeded(stack);
    367         addStackReferenceIfNeeded(stack);
    368     }
    369 
    370     private void addStackReferenceIfNeeded(ActivityStack stack) {
    371         final int activityType = stack.getActivityType();
    372         final int windowingMode = stack.getWindowingMode();
    373 
    374         if (activityType == ACTIVITY_TYPE_HOME) {
    375             if (mHomeStack != null && mHomeStack != stack) {
    376                 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
    377                         + mHomeStack + " already exist on display=" + this + " stack=" + stack);
    378             }
    379             mHomeStack = stack;
    380         } else if (activityType == ACTIVITY_TYPE_RECENTS) {
    381             if (mRecentsStack != null && mRecentsStack != stack) {
    382                 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
    383                         + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
    384             }
    385             mRecentsStack = stack;
    386         }
    387         if (windowingMode == WINDOWING_MODE_PINNED) {
    388             if (mPinnedStack != null && mPinnedStack != stack) {
    389                 throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
    390                         + mPinnedStack + " already exist on display=" + this
    391                         + " stack=" + stack);
    392             }
    393             mPinnedStack = stack;
    394         } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
    395             if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
    396                 throw new IllegalArgumentException("addStackReferenceIfNeeded:"
    397                         + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
    398                         + " already exist on display=" + this + " stack=" + stack);
    399             }
    400             mSplitScreenPrimaryStack = stack;
    401             onSplitScreenModeActivated();
    402         }
    403     }
    404 
    405     private void removeStackReferenceIfNeeded(ActivityStack stack) {
    406         if (stack == mHomeStack) {
    407             mHomeStack = null;
    408         } else if (stack == mRecentsStack) {
    409             mRecentsStack = null;
    410         } else if (stack == mPinnedStack) {
    411             mPinnedStack = null;
    412         } else if (stack == mSplitScreenPrimaryStack) {
    413             mSplitScreenPrimaryStack = null;
    414             // Inform the reset of the system that split-screen mode was dismissed so things like
    415             // resizing all the other stacks can take place.
    416             onSplitScreenModeDismissed();
    417         }
    418     }
    419 
    420     private void onSplitScreenModeDismissed() {
    421         mSupervisor.mWindowManager.deferSurfaceLayout();
    422         try {
    423             // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
    424             for (int i = mStacks.size() - 1; i >= 0; --i) {
    425                 final ActivityStack otherStack = mStacks.get(i);
    426                 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
    427                     continue;
    428                 }
    429                 otherStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN, false /* animate */,
    430                         false /* showRecents */, false /* enteringSplitScreenMode */,
    431                         true /* deferEnsuringVisibility */);
    432             }
    433         } finally {
    434             final ActivityStack topFullscreenStack =
    435                     getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
    436             if (topFullscreenStack != null && mHomeStack != null && !isTopStack(mHomeStack)) {
    437                 // Whenever split-screen is dismissed we want the home stack directly behind the
    438                 // current top fullscreen stack so it shows up when the top stack is finished.
    439                 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
    440                 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
    441                 // once we have that.
    442                 mHomeStack.moveToFront("onSplitScreenModeDismissed");
    443                 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
    444             }
    445             mSupervisor.mWindowManager.continueSurfaceLayout();
    446         }
    447     }
    448 
    449     private void onSplitScreenModeActivated() {
    450         mSupervisor.mWindowManager.deferSurfaceLayout();
    451         try {
    452             // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
    453             for (int i = mStacks.size() - 1; i >= 0; --i) {
    454                 final ActivityStack otherStack = mStacks.get(i);
    455                 if (otherStack == mSplitScreenPrimaryStack
    456                         || !otherStack.affectedBySplitScreenResize()) {
    457                     continue;
    458                 }
    459                 otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
    460                         false /* animate */, false /* showRecents */,
    461                         true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */);
    462             }
    463         } finally {
    464             mSupervisor.mWindowManager.continueSurfaceLayout();
    465         }
    466     }
    467 
    468     /**
    469      * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
    470      * @param windowingMode The windowing mode we are checking support for.
    471      * @param supportsMultiWindow If we should consider support for multi-window mode in general.
    472      * @param supportsSplitScreen If we should consider support for split-screen multi-window.
    473      * @param supportsFreeform If we should consider support for freeform multi-window.
    474      * @param supportsPip If we should consider support for picture-in-picture mutli-window.
    475      * @param activityType The activity type under consideration.
    476      * @return true if the windowing mode is supported.
    477      */
    478     private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
    479             boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
    480             int activityType) {
    481 
    482         if (windowingMode == WINDOWING_MODE_UNDEFINED
    483                 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
    484             return true;
    485         }
    486         if (!supportsMultiWindow) {
    487             return false;
    488         }
    489 
    490         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
    491                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
    492             return supportsSplitScreen
    493                     && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
    494         }
    495 
    496         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
    497             return false;
    498         }
    499 
    500         if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
    501             return false;
    502         }
    503         return true;
    504     }
    505 
    506     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
    507             @Nullable TaskRecord task, int activityType) {
    508 
    509         // First preference if the windowing mode in the activity options if set.
    510         int windowingMode = (options != null)
    511                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
    512 
    513         // If windowing mode is unset, then next preference is the candidate task, then the
    514         // activity record.
    515         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
    516             if (task != null) {
    517                 windowingMode = task.getWindowingMode();
    518             }
    519             if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
    520                 windowingMode = r.getWindowingMode();
    521             }
    522             if (windowingMode == WINDOWING_MODE_UNDEFINED) {
    523                 // Use the display's windowing mode.
    524                 windowingMode = getWindowingMode();
    525             }
    526         }
    527 
    528         // Make sure the windowing mode we are trying to use makes sense for what is supported.
    529         final ActivityManagerService service = mSupervisor.mService;
    530         boolean supportsMultiWindow = service.mSupportsMultiWindow;
    531         boolean supportsSplitScreen = service.mSupportsSplitScreenMultiWindow;
    532         boolean supportsFreeform = service.mSupportsFreeformWindowManagement;
    533         boolean supportsPip = service.mSupportsPictureInPicture;
    534         if (supportsMultiWindow) {
    535             if (task != null) {
    536                 supportsMultiWindow = task.isResizeable();
    537                 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
    538                 // TODO: Do we need to check for freeform and Pip support here?
    539             } else if (r != null) {
    540                 supportsMultiWindow = r.isResizeable();
    541                 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
    542                 supportsFreeform = r.supportsFreeform();
    543                 supportsPip = r.supportsPictureInPicture();
    544             }
    545         }
    546 
    547         final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
    548         if (!inSplitScreenMode
    549                 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
    550             // Switch to fullscreen windowing mode if we are not in split-screen mode and we are
    551             // trying to launch in split-screen secondary.
    552             windowingMode = WINDOWING_MODE_FULLSCREEN;
    553         } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
    554                 && supportsSplitScreen) {
    555             windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
    556         }
    557 
    558         if (windowingMode != WINDOWING_MODE_UNDEFINED
    559                 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
    560                 supportsFreeform, supportsPip, activityType)) {
    561             return windowingMode;
    562         }
    563         // Try to use the display's windowing mode otherwise fallback to fullscreen.
    564         windowingMode = getWindowingMode();
    565         return windowingMode != WINDOWING_MODE_UNDEFINED
    566                 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
    567     }
    568 
    569     /**
    570      * Get the topmost stack on the display. It may be different from focused stack, because
    571      * focus may be on another display.
    572      */
    573     ActivityStack getTopStack() {
    574         return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
    575     }
    576 
    577     boolean isTopStack(ActivityStack stack) {
    578         return stack == getTopStack();
    579     }
    580 
    581     boolean isTopNotPinnedStack(ActivityStack stack) {
    582         for (int i = mStacks.size() - 1; i >= 0; --i) {
    583             final ActivityStack current = mStacks.get(i);
    584             if (!current.inPinnedWindowingMode()) {
    585                 return current == stack;
    586             }
    587         }
    588         return false;
    589     }
    590 
    591     ActivityStack getTopStackInWindowingMode(int windowingMode) {
    592         for (int i = mStacks.size() - 1; i >= 0; --i) {
    593             final ActivityStack current = mStacks.get(i);
    594             if (windowingMode == current.getWindowingMode()) {
    595                 return current;
    596             }
    597         }
    598         return null;
    599     }
    600 
    601     int getIndexOf(ActivityStack stack) {
    602         return mStacks.indexOf(stack);
    603     }
    604 
    605     void onLockTaskPackagesUpdated() {
    606         for (int i = mStacks.size() - 1; i >= 0; --i) {
    607             mStacks.get(i).onLockTaskPackagesUpdated();
    608         }
    609     }
    610 
    611     /** We are in the process of exiting split-screen mode. */
    612     void onExitingSplitScreenMode() {
    613         // Remove reference to the primary-split-screen stack so it no longer has any effect on the
    614         // display. For example, we want to be able to create fullscreen stack for standard activity
    615         // types when exiting split-screen mode.
    616         mSplitScreenPrimaryStack = null;
    617     }
    618 
    619     ActivityStack getSplitScreenPrimaryStack() {
    620         return mSplitScreenPrimaryStack;
    621     }
    622 
    623     boolean hasSplitScreenPrimaryStack() {
    624         return mSplitScreenPrimaryStack != null;
    625     }
    626 
    627     PinnedActivityStack getPinnedStack() {
    628         return (PinnedActivityStack) mPinnedStack;
    629     }
    630 
    631     boolean hasPinnedStack() {
    632         return mPinnedStack != null;
    633     }
    634 
    635     @Override
    636     public String toString() {
    637         return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
    638     }
    639 
    640     @Override
    641     protected int getChildCount() {
    642         return mStacks.size();
    643     }
    644 
    645     @Override
    646     protected ActivityStack getChildAt(int index) {
    647         return mStacks.get(index);
    648     }
    649 
    650     @Override
    651     protected ConfigurationContainer getParent() {
    652         return mSupervisor;
    653     }
    654 
    655     boolean isPrivate() {
    656         return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
    657     }
    658 
    659     boolean isUidPresent(int uid) {
    660         for (ActivityStack stack : mStacks) {
    661             if (stack.isUidPresent(uid)) {
    662                 return true;
    663             }
    664         }
    665         return false;
    666     }
    667 
    668     void remove() {
    669         final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
    670         while (getChildCount() > 0) {
    671             final ActivityStack stack = getChildAt(0);
    672             if (destroyContentOnRemoval) {
    673                 // Override the stack configuration to make it equal to the current applied one, so
    674                 // that we don't accidentally report configuration change to activities that are
    675                 // going to be finished.
    676                 stack.onOverrideConfigurationChanged(stack.getConfiguration());
    677                 mSupervisor.moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY,
    678                         false /* onTop */);
    679                 stack.finishAllActivitiesLocked(true /* immediately */);
    680             } else {
    681                 // Moving all tasks to fullscreen stack, because it's guaranteed to be
    682                 // a valid launch stack for all activities. This way the task history from
    683                 // external display will be preserved on primary after move.
    684                 mSupervisor.moveTasksToFullscreenStackLocked(stack, true /* onTop */);
    685             }
    686         }
    687 
    688         mWindowContainerController.removeContainer();
    689         mWindowContainerController = null;
    690     }
    691 
    692     /** Update and get all UIDs that are present on the display and have access to it. */
    693     IntArray getPresentUIDs() {
    694         mDisplayAccessUIDs.clear();
    695         for (ActivityStack stack : mStacks) {
    696             stack.getPresentUIDs(mDisplayAccessUIDs);
    697         }
    698         return mDisplayAccessUIDs;
    699     }
    700 
    701     private boolean shouldDestroyContentOnRemove() {
    702         return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
    703     }
    704 
    705     boolean shouldSleep() {
    706         return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
    707                 && (mSupervisor.mService.mRunningVoice == null);
    708     }
    709 
    710     /**
    711      * @return the stack currently above the {@param stack}.  Can be null if the {@param stack} is
    712      *         already top-most.
    713      */
    714     ActivityStack getStackAbove(ActivityStack stack) {
    715         final int stackIndex = mStacks.indexOf(stack) + 1;
    716         return (stackIndex < mStacks.size()) ? mStacks.get(stackIndex) : null;
    717     }
    718 
    719     /**
    720      * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
    721      * Generally used in conjunction with {@link #moveStackBehindStack}.
    722      */
    723     void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
    724         if (stack.shouldBeVisible(null)) {
    725             // Skip if the stack is already visible
    726             return;
    727         }
    728 
    729         // Move the stack to the bottom to not affect the following visibility checks
    730         positionChildAtBottom(stack);
    731 
    732         // Find the next position where the stack should be placed
    733         final int numStacks = mStacks.size();
    734         for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
    735             final ActivityStack s = mStacks.get(stackNdx);
    736             if (s == stack) {
    737                 continue;
    738             }
    739             final int winMode = s.getWindowingMode();
    740             final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN ||
    741                     winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
    742             if (s.shouldBeVisible(null) && isValidWindowingMode) {
    743                 // Move the provided stack to behind this stack
    744                 positionChildAt(stack, Math.max(0, stackNdx - 1));
    745                 break;
    746             }
    747         }
    748     }
    749 
    750     /**
    751      * Moves the {@param stack} behind the given {@param behindStack} if possible. If
    752      * {@param behindStack} is not currently in the display, then then the stack is moved to the
    753      * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
    754      */
    755     void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
    756         if (behindStack == null || behindStack == stack) {
    757             return;
    758         }
    759 
    760         // Note that positionChildAt will first remove the given stack before inserting into the
    761         // list, so we need to adjust the insertion index to account for the removed index
    762         // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
    763         //       position internally
    764         final int stackIndex = mStacks.indexOf(stack);
    765         final int behindStackIndex = mStacks.indexOf(behindStack);
    766         final int insertIndex = stackIndex <= behindStackIndex
    767                 ? behindStackIndex - 1 : behindStackIndex;
    768         positionChildAt(stack, Math.max(0, insertIndex));
    769     }
    770 
    771     boolean isSleeping() {
    772         return mSleeping;
    773     }
    774 
    775     void setIsSleeping(boolean asleep) {
    776         mSleeping = asleep;
    777     }
    778 
    779     /**
    780      * Adds a listener to be notified whenever the stack order in the display changes. Currently
    781      * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
    782      * current animation when the system state changes.
    783      */
    784     void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
    785         if (!mStackOrderChangedCallbacks.contains(listener)) {
    786             mStackOrderChangedCallbacks.add(listener);
    787         }
    788     }
    789 
    790     /**
    791      * Removes a previously registered stack order change listener.
    792      */
    793     void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
    794         mStackOrderChangedCallbacks.remove(listener);
    795     }
    796 
    797     private void onStackOrderChanged() {
    798         for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
    799             mStackOrderChangedCallbacks.get(i).onStackOrderChanged();
    800         }
    801     }
    802 
    803     /**
    804      * See {@link DisplayWindowController#deferUpdateImeTarget()}
    805      */
    806     public void deferUpdateImeTarget() {
    807         mWindowContainerController.deferUpdateImeTarget();
    808     }
    809 
    810     /**
    811      * See {@link DisplayWindowController#deferUpdateImeTarget()}
    812      */
    813     public void continueUpdateImeTarget() {
    814         mWindowContainerController.continueUpdateImeTarget();
    815     }
    816 
    817     public void dump(PrintWriter pw, String prefix) {
    818         pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
    819         final String myPrefix = prefix + " ";
    820         if (mHomeStack != null) {
    821             pw.println(myPrefix + "mHomeStack=" + mHomeStack);
    822         }
    823         if (mRecentsStack != null) {
    824             pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
    825         }
    826         if (mPinnedStack != null) {
    827             pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
    828         }
    829         if (mSplitScreenPrimaryStack != null) {
    830             pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
    831         }
    832     }
    833 
    834     public void dumpStacks(PrintWriter pw) {
    835         for (int i = mStacks.size() - 1; i >= 0; --i) {
    836             pw.print(mStacks.get(i).mStackId);
    837             if (i > 0) {
    838                 pw.print(",");
    839             }
    840         }
    841     }
    842 
    843     public void writeToProto(ProtoOutputStream proto, long fieldId) {
    844         final long token = proto.start(fieldId);
    845         super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
    846         proto.write(ID, mDisplayId);
    847         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
    848             final ActivityStack stack = mStacks.get(stackNdx);
    849             stack.writeToProto(proto, STACKS);
    850         }
    851         proto.end(token);
    852     }
    853 
    854     /**
    855      * Callback for when the order of the stacks in the display changes.
    856      */
    857     interface OnStackOrderChangedListener {
    858         void onStackOrderChanged();
    859     }
    860 }
    861