Migrated some windowing methods from StackId to WindowConfiguration

First pass at transitioning away from using stack ids for windowing mode
to WindowConfiguration. Added some TODO that will require the introduction
of applicationType in WindowConfiguration before additional conversation
can be done.

Test: bit FrameworksServicesTests:com.android.server.wm.WindowConfigurationTests
Test: adb shell am instrument -w -e package com.android.server.wm com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
Test: go/wm-smoke
Change-Id: I2b315623faa16445a9f942e082089123842cb5a1
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 757795e..82c44ea 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3203,9 +3203,8 @@
 
 
     /**
-     * Moves the activity from
-     * {@link android.app.ActivityManager.StackId#FREEFORM_WORKSPACE_STACK_ID} to
-     * {@link android.app.ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} stack.
+     * Moves the activity from {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing mode to
+     * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
      *
      * @hide
      */
@@ -3214,14 +3213,6 @@
         ActivityManager.getService().exitFreeformMode(mToken);
     }
 
-    /** Returns the current stack Id for the window.
-     * @hide
-     */
-    @Override
-    public int getWindowStackId() throws RemoteException {
-        return ActivityManager.getService().getActivityStackId(mToken);
-    }
-
     /**
      * Puts the activity in picture-in-picture mode if the activity supports.
      * @see android.R.attr#supportsPictureInPicture
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5b16b7d..a0132b1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -699,45 +699,21 @@
         /** Start of ID range used by stacks that are created dynamically. */
         public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
 
+        // TODO: Figure-out a way to remove this.
         public static boolean isStaticStack(int stackId) {
             return stackId >= FIRST_STATIC_STACK_ID && stackId <= LAST_STATIC_STACK_ID;
         }
 
+        // TODO: It seems this mostly means a stack on a secondary display now. Need to see if
+        // there are other meanings. If not why not just use information from the display?
         public static boolean isDynamicStack(int stackId) {
             return stackId >= FIRST_DYNAMIC_STACK_ID;
         }
 
         /**
-         * Returns true if the activities contained in the input stack display a shadow around
-         * their border.
-         */
-        public static boolean hasWindowShadow(int stackId) {
-            return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == PINNED_STACK_ID;
-        }
-
-        /**
-         * Returns true if the activities contained in the input stack display a decor view.
-         */
-        public static boolean hasWindowDecor(int stackId) {
-            return stackId == FREEFORM_WORKSPACE_STACK_ID;
-        }
-
-        /**
-         * Returns true if the tasks contained in the stack can be resized independently of the
-         * stack.
-         */
-        public static boolean isTaskResizeAllowed(int stackId) {
-            return stackId == FREEFORM_WORKSPACE_STACK_ID;
-        }
-
-        /** Returns true if the task bounds should persist across power cycles. */
-        public static boolean persistTaskBounds(int stackId) {
-            return stackId == FREEFORM_WORKSPACE_STACK_ID;
-        }
-
-        /**
          * Returns true if dynamic stacks are allowed to be visible behind the input stack.
          */
+        // TODO: Figure-out a way to remove.
         public static boolean isDynamicStacksVisibleBehindAllowed(int stackId) {
             return stackId == PINNED_STACK_ID || stackId == ASSISTANT_STACK_ID;
         }
@@ -746,6 +722,7 @@
          * Returns true if we try to maintain focus in the current stack when the top activity
          * finishes.
          */
+        // TODO: Figure-out a way to remove. Probably isn't needed in the new world...
         public static boolean keepFocusInStackIfPossible(int stackId) {
             return stackId == FREEFORM_WORKSPACE_STACK_ID
                     || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
@@ -754,6 +731,7 @@
         /**
          * Returns true if Stack size is affected by the docked stack changing size.
          */
+        // TODO: Figure-out a way to remove.
         public static boolean isResizeableByDockedStack(int stackId) {
             return isStaticStack(stackId) && stackId != DOCKED_STACK_ID
                     && stackId != PINNED_STACK_ID && stackId != ASSISTANT_STACK_ID;
@@ -763,6 +741,7 @@
          * Returns true if the size of tasks in the input stack are affected by the docked stack
          * changing size.
          */
+        // TODO: What is the difference between this method and the one above??
         public static boolean isTaskResizeableByDockedStack(int stackId) {
             return isStaticStack(stackId) && stackId != FREEFORM_WORKSPACE_STACK_ID
                     && stackId != DOCKED_STACK_ID && stackId != PINNED_STACK_ID
@@ -788,16 +767,6 @@
         }
 
         /**
-         * Return whether a stackId is a stack containing floating windows. Floating windows
-         * are laid out differently as they are allowed to extend past the display bounds
-         * without overscan insets.
-         */
-        public static boolean tasksAreFloating(int stackId) {
-            return stackId == FREEFORM_WORKSPACE_STACK_ID
-                || stackId == PINNED_STACK_ID;
-        }
-
-        /**
          * Return whether a stackId is a stack that be a backdrop to a translucent activity.  These
          * are generally fullscreen stacks.
          */
@@ -821,21 +790,6 @@
         }
 
         /**
-         * Returns true if the windows in the stack can receive input keys.
-         */
-        public static boolean canReceiveKeys(int stackId) {
-            return stackId != PINNED_STACK_ID;
-        }
-
-        /**
-         * Returns true if the stack can be visible above lockscreen.
-         */
-        public static boolean isAllowedOverLockscreen(int stackId) {
-            return stackId == HOME_STACK_ID || stackId == FULLSCREEN_WORKSPACE_STACK_ID ||
-                    stackId == ASSISTANT_STACK_ID;
-        }
-
-        /**
          * Returns true if activities from stasks in the given {@param stackId} are allowed to
          * enter picture-in-picture.
          */
@@ -844,10 +798,6 @@
                     stackId != RECENTS_STACK_ID;
         }
 
-        public static boolean isAlwaysOnTop(int stackId) {
-            return stackId == PINNED_STACK_ID;
-        }
-
         /**
          * Returns true if the top task in the task is allowed to return home when finished and
          * there are other tasks in the stack.
@@ -865,27 +815,12 @@
         }
 
         /**
-         * Returns true if any visible windows belonging to apps in this stack should be kept on
-         * screen when the app is killed due to something like the low memory killer.
-         */
-        public static boolean keepVisibleDeadAppWindowOnScreen(int stackId) {
-            return stackId != PINNED_STACK_ID;
-        }
-
-        /**
-         * Returns true if the backdrop on the client side should match the frame of the window.
-         * Returns false, if the backdrop should be fullscreen.
-         */
-        public static boolean useWindowFrameForBackdrop(int stackId) {
-            return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == PINNED_STACK_ID;
-        }
-
-        /**
          * Returns true if a window from the specified stack with {@param stackId} are normally
          * fullscreen, i. e. they can become the top opaque fullscreen window, meaning that it
          * controls system bars, lockscreen occluded/dismissing state, screen rotation animation,
          * etc.
          */
+        // TODO: What about the other side of docked stack if we move this to WindowConfiguration?
         public static boolean normallyFullscreenWindows(int stackId) {
             return stackId != PINNED_STACK_ID && stackId != FREEFORM_WORKSPACE_STACK_ID
                     && stackId != DOCKED_STACK_ID;
@@ -896,6 +831,7 @@
          * multi-window mode.
          * @see android.app.ActivityManager#supportsMultiWindow
          */
+        // TODO: What about the other side of docked stack if we move this to WindowConfiguration?
         public static boolean isMultiWindowStack(int stackId) {
             return stackId == PINNED_STACK_ID || stackId == FREEFORM_WORKSPACE_STACK_ID
                     || stackId == DOCKED_STACK_ID;
@@ -908,21 +844,6 @@
             return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID;
         }
 
-        /**
-         * Returns true if this stack may be scaled without resizing, and windows within may need
-         * to be configured as such.
-         */
-        public static boolean windowsAreScaleable(int stackId) {
-            return stackId == PINNED_STACK_ID;
-        }
-
-        /**
-         * Returns true if windows in this stack should be given move animations by default.
-         */
-        public static boolean hasMovementAnimations(int stackId) {
-            return stackId != PINNED_STACK_ID;
-        }
-
         /** Returns true if the input stack and its content can affect the device orientation. */
         public static boolean canSpecifyOrientation(int stackId) {
             return stackId == HOME_STACK_ID
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 897e42b..b5aaade 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -478,7 +478,6 @@
      * different stack.
      */
     void positionTaskInStack(int taskId, int stackId, int position);
-    int getActivityStackId(in IBinder token);
     void exitFreeformMode(in IBinder token);
     void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
             in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index e4ec8c3..d5d7107 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -277,6 +277,90 @@
                 + " mWindowingMode=" + windowingModeToString(mWindowingMode) + "}";
     }
 
+    /**
+     * Returns true if the activities associated with this window configuration display a shadow
+     * around their border.
+     */
+    public boolean hasWindowShadow() {
+        return tasksAreFloating();
+    }
+
+    /**
+     * Returns true if the activities associated with this window configuration display a decor
+     * view.
+     */
+    public boolean hasWindowDecorCaption() {
+        return mWindowingMode == WINDOWING_MODE_FREEFORM;
+    }
+
+    /**
+     * Returns true if the tasks associated with this window configuration can be resized
+     * independently of their parent container.
+     */
+    public boolean canResizeTask() {
+        return mWindowingMode == WINDOWING_MODE_FREEFORM;
+    }
+
+    /** Returns true if the task bounds should persist across power cycles. */
+    public boolean persistTaskBounds() {
+        return mWindowingMode == WINDOWING_MODE_FREEFORM;
+    }
+
+    /**
+     * Returns true if the tasks associated with this window configuration are floating.
+     * Floating tasks are laid out differently as they are allowed to extend past the display bounds
+     * without overscan insets.
+     */
+    public boolean tasksAreFloating() {
+        return mWindowingMode == WINDOWING_MODE_FREEFORM || mWindowingMode == WINDOWING_MODE_PINNED;
+    }
+
+    /**
+     * Returns true if the windows associated with this window configuration can receive input keys.
+     */
+    public boolean canReceiveKeys() {
+        return mWindowingMode != WINDOWING_MODE_PINNED;
+    }
+
+    /**
+     * Returns true if the container associated with this window configuration is always-on-top of
+     * its siblings.
+     */
+    public boolean isAlwaysOnTop() {
+        return mWindowingMode == WINDOWING_MODE_PINNED;
+    }
+
+    /**
+     * Returns true if any visible windows belonging to apps with this window configuration should
+     * be kept on screen when the app is killed due to something like the low memory killer.
+     */
+    public boolean keepVisibleDeadAppWindowOnScreen() {
+        return mWindowingMode != WINDOWING_MODE_PINNED;
+    }
+
+    /**
+     * Returns true if the backdrop on the client side should match the frame of the window.
+     * Returns false, if the backdrop should be fullscreen.
+     */
+    public boolean useWindowFrameForBackdrop() {
+        return mWindowingMode == WINDOWING_MODE_FREEFORM || mWindowingMode == WINDOWING_MODE_PINNED;
+    }
+
+    /**
+     * Returns true if this container may be scaled without resizing, and windows within may need
+     * to be configured as such.
+     */
+    public boolean windowsAreScaleable() {
+        return mWindowingMode == WINDOWING_MODE_PINNED;
+    }
+
+    /**
+     * Returns true if windows in this container should be given move animations by default.
+     */
+    public boolean hasMovementAnimations() {
+        return mWindowingMode == WINDOWING_MODE_PINNED;
+    }
+
     private static String windowingModeToString(@WindowingMode int windowingMode) {
         switch (windowingMode) {
             case WINDOWING_MODE_UNDEFINED: return "undefined";
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 7d780f1..176927f 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -26,6 +26,7 @@
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
 import android.annotation.SystemApi;
+import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -611,8 +612,8 @@
     public interface WindowControllerCallback {
         /**
          * Moves the activity from
-         * {@link android.app.ActivityManager.StackId#FREEFORM_WORKSPACE_STACK_ID} to
-         * {@link android.app.ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} stack.
+         * Moves the activity from {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing
+         * mode to {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
          */
         void exitFreeformMode() throws RemoteException;
 
@@ -622,9 +623,6 @@
          */
         void enterPictureInPictureModeIfPossible();
 
-        /** Returns the current stack Id for the window. */
-        int getWindowStackId() throws RemoteException;
-
         /** Returns whether the window belongs to the task root. */
         boolean isTaskRoot();
     }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 60fbbe9..bd94fc7 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.policy;
 
+import android.app.WindowConfiguration;
 import android.graphics.Outline;
 import android.view.ViewOutlineProvider;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -82,11 +83,8 @@
 import android.widget.FrameLayout;
 import android.widget.PopupWindow;
 
-import static android.app.ActivityManager.StackId;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.os.Build.VERSION_CODES.M;
 import static android.os.Build.VERSION_CODES.N;
@@ -234,10 +232,6 @@
     // If the window type does not require such a view, this member might be null.
     DecorCaptionView mDecorCaptionView;
 
-    // Stack window is currently in. Since querying and changing the stack is expensive,
-    // this is the stack value the window is currently set up for.
-    int mStackId;
-
     private boolean mWindowResizeCallbacksAdded = false;
     private Drawable.Callback mLastBackgroundDrawableCb = null;
     private BackdropFrameRenderer mBackdropFrameRenderer = null;
@@ -1470,7 +1464,8 @@
         invalidate();
 
         int opacity = PixelFormat.OPAQUE;
-        if (StackId.hasWindowShadow(mStackId)) {
+        final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration;
+        if (winConfig.hasWindowShadow()) {
             // If the window has a shadow, it must be translucent.
             opacity = PixelFormat.TRANSLUCENT;
         } else{
@@ -1860,35 +1855,33 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        int workspaceId = getStackId();
-        if (mStackId != workspaceId) {
-            mStackId = workspaceId;
-            if (mDecorCaptionView == null && StackId.hasWindowDecor(mStackId)) {
-                // Configuration now requires a caption.
-                final LayoutInflater inflater = mWindow.getLayoutInflater();
-                mDecorCaptionView = createDecorCaptionView(inflater);
-                if (mDecorCaptionView != null) {
-                    if (mDecorCaptionView.getParent() == null) {
-                        addView(mDecorCaptionView, 0,
-                                new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
-                    }
-                    removeView(mContentRoot);
-                    mDecorCaptionView.addView(mContentRoot,
-                            new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
+
+        final boolean displayWindowDecor =
+                newConfig.windowConfiguration.hasWindowDecorCaption();
+        if (mDecorCaptionView == null && displayWindowDecor) {
+            // Configuration now requires a caption.
+            final LayoutInflater inflater = mWindow.getLayoutInflater();
+            mDecorCaptionView = createDecorCaptionView(inflater);
+            if (mDecorCaptionView != null) {
+                if (mDecorCaptionView.getParent() == null) {
+                    addView(mDecorCaptionView, 0,
+                            new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
                 }
-            } else if (mDecorCaptionView != null) {
-                // We might have to change the kind of surface before we do anything else.
-                mDecorCaptionView.onConfigurationChanged(StackId.hasWindowDecor(mStackId));
-                enableCaption(StackId.hasWindowDecor(workspaceId));
+                removeView(mContentRoot);
+                mDecorCaptionView.addView(mContentRoot,
+                        new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
             }
+        } else if (mDecorCaptionView != null) {
+            // We might have to change the kind of surface before we do anything else.
+            mDecorCaptionView.onConfigurationChanged(displayWindowDecor);
+            enableCaption(displayWindowDecor);
         }
+
         updateAvailableWidth();
         initializeElevation();
     }
 
     void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
-        mStackId = getStackId();
-
         if (mBackdropFrameRenderer != null) {
             loadBackgroundDrawablesIfNeeded();
             mBackdropFrameRenderer.onResourcesLoaded(
@@ -1950,8 +1943,9 @@
         final WindowManager.LayoutParams attrs = mWindow.getAttributes();
         final boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
                 attrs.type == TYPE_APPLICATION || attrs.type == TYPE_DRAWN_APPLICATION;
+        final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration;
         // Only a non floating application window on one of the allowed workspaces can get a caption
-        if (!mWindow.isFloating() && isApplication && StackId.hasWindowDecor(mStackId)) {
+        if (!mWindow.isFloating() && isApplication && winConfig.hasWindowDecorCaption()) {
             // Dependent on the brightness of the used title we either use the
             // dark or the light button frame.
             if (decorCaptionView == null) {
@@ -2064,28 +2058,6 @@
         return drawable;
     }
 
-    /**
-     * Returns the Id of the stack which contains this window.
-     * Note that if no stack can be determined - which usually means that it was not
-     * created for an activity - the fullscreen stack ID will be returned.
-     * @return Returns the stack id which contains this window.
-     **/
-    private int getStackId() {
-        int workspaceId = INVALID_STACK_ID;
-        final Window.WindowControllerCallback callback = mWindow.getWindowControllerCallback();
-        if (callback != null) {
-            try {
-                workspaceId = callback.getWindowStackId();
-            } catch (RemoteException ex) {
-                Log.e(mLogTag, "Failed to get the workspace ID of a PhoneWindow.");
-            }
-        }
-        if (workspaceId == INVALID_STACK_ID) {
-            return FULLSCREEN_WORKSPACE_STACK_ID;
-        }
-        return workspaceId;
-    }
-
     void clearContentView() {
         if (mDecorCaptionView != null) {
             mDecorCaptionView.removeContentView();
@@ -2238,7 +2210,9 @@
         final boolean wasAdjustedForStack = mElevationAdjustedForStack;
         // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
         // since the shadow is bound to the content size and not the target size.
-        if ((mStackId == FREEFORM_WORKSPACE_STACK_ID) && !isResizing()) {
+        final int windowingMode =
+                getResources().getConfiguration().windowConfiguration.getWindowingMode();
+        if ((windowingMode == WINDOWING_MODE_FREEFORM) && !isResizing()) {
             elevation = hasWindowFocus() ?
                     DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
             // Add a maximum shadow height value to the top level view.
@@ -2251,7 +2225,7 @@
             // Convert the DP elevation into physical pixels.
             elevation = dipToPx(elevation);
             mElevationAdjustedForStack = true;
-        } else if (mStackId == PINNED_STACK_ID) {
+        } else if (windowingMode == WINDOWING_MODE_PINNED) {
             elevation = dipToPx(DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP);
             mElevationAdjustedForStack = true;
         } else {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 70fdcef..f6aa44a4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10150,7 +10150,7 @@
                 //   that task to freeform
                 // - otherwise the task is not moved
                 int stackId = task.getStackId();
-                if (!StackId.isTaskResizeAllowed(stackId)) {
+                if (!task.getWindowConfiguration().canResizeTask()) {
                     throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
                 }
                 if (bounds == null && stackId == FREEFORM_WORKSPACE_STACK_ID) {
@@ -10516,17 +10516,6 @@
     }
 
     @Override
-    public int getActivityStackId(IBinder token) throws RemoteException {
-        synchronized (this) {
-            ActivityStack stack = ActivityRecord.getStackLocked(token);
-            if (stack == null) {
-                return INVALID_STACK_ID;
-            }
-            return stack.mStackId;
-        }
-    }
-
-    @Override
     public void exitFreeformMode(IBinder token) throws RemoteException {
         synchronized (this) {
             long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index f396e9e..aae98a6 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -4,11 +4,12 @@
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
 import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-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.PINNED_STACK_ID;
 import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
+import static android.app.WindowConfiguration.WINDOWING_MODE_DOCKED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME;
@@ -117,17 +118,19 @@
         }
         mWindowState = WINDOW_STATE_INVALID;
         stack = mSupervisor.getFocusedStack();
-        if (stack.mStackId == PINNED_STACK_ID) {
+        int windowingMode = stack.getWindowingMode();
+        if (windowingMode == WINDOWING_MODE_PINNED) {
             stack = mSupervisor.findStackBehind(stack);
+            windowingMode = stack.getWindowingMode();
         }
         if (StackId.isHomeOrRecentsStack(stack.mStackId)
-                || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+                || windowingMode == WINDOWING_MODE_FULLSCREEN) {
             mWindowState = WINDOW_STATE_STANDARD;
-        } else if (stack.mStackId == DOCKED_STACK_ID) {
+        } else if (windowingMode == WINDOWING_MODE_DOCKED) {
             Slog.wtf(TAG, "Docked stack shouldn't be the focused stack, because it reported not"
                     + " being visible.");
             mWindowState = WINDOW_STATE_INVALID;
-        } else if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+        } else if (windowingMode == WINDOWING_MODE_FREEFORM) {
             mWindowState = WINDOW_STATE_FREEFORM;
         } else if (stack.mStackId == ASSISTANT_STACK_ID) {
             mWindowState = WINDOW_STATE_ASSISTANT;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 8ca6645..be81abd 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1118,19 +1118,14 @@
         return mActivityType == ASSISTANT_ACTIVITY_TYPE;
     }
 
-    boolean isApplicationActivity() {
-        return mActivityType == APPLICATION_ACTIVITY_TYPE;
-    }
-
     boolean isPersistable() {
         return (info.persistableMode == PERSIST_ROOT_ONLY ||
                 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
-                (intent == null ||
-                        (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
+                (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
     }
 
     boolean isFocusable() {
-        return StackId.canReceiveKeys(task.getStackId()) || isAlwaysFocusable();
+        return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
     }
 
     boolean isResizeable() {
@@ -2315,7 +2310,7 @@
         // We must base this on the parent configuration, because we set our override
         // configuration's appBounds based on the result of this method. If we used our own
         // configuration, it would be influenced by past invocations.
-        final Rect appBounds = getParent().getConfiguration().windowConfiguration.getAppBounds();
+        final Rect appBounds = getParent().getWindowConfiguration().getAppBounds();
         final int containingAppWidth = appBounds.width();
         final int containingAppHeight = appBounds.height();
         int maxActivityWidth = containingAppWidth;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 978d586..a9a06d0 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -904,7 +904,8 @@
             int addIndex = mStacks.size();
             if (addIndex > 0) {
                 final ActivityStack topStack = mStacks.get(addIndex - 1);
-                if (StackId.isAlwaysOnTop(topStack.mStackId) && topStack != this) {
+                if (topStack.getWindowConfiguration().isAlwaysOnTop()
+                        && topStack != this) {
                     // If the top stack is always on top, we move this stack just below it.
                     addIndex--;
                 }
@@ -916,7 +917,7 @@
     }
 
     boolean isFocusable() {
-        if (StackId.canReceiveKeys(mStackId)) {
+        if (getWindowConfiguration().canReceiveKeys()) {
             return true;
         }
         // The stack isn't focusable. See if its top activity is focusable to force focus on the
@@ -1721,11 +1722,12 @@
         }
         final int stackBehindTopId = (stackBehindTopIndex >= 0)
                 ? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
-        if (topStackId == DOCKED_STACK_ID || StackId.isAlwaysOnTop(topStackId)) {
+        final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop();
+        if (topStackId == DOCKED_STACK_ID || alwaysOnTop) {
             if (stackIndex == stackBehindTopIndex) {
                 // Stacks directly behind the docked or pinned stack are always visible.
                 return STACK_VISIBLE;
-            } else if (StackId.isAlwaysOnTop(topStackId) && stackIndex == stackBehindTopIndex - 1) {
+            } else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) {
                 // Otherwise, this stack can also be visible if it is directly behind a docked stack
                 // or translucent assistant stack behind an always-on-top top-most stack
                 if (stackBehindTopId == DOCKED_STACK_ID) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 441df0b..752dc12 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2362,8 +2362,9 @@
             return;
         }
 
-        if (!allowResizeInDockedMode && !StackId.tasksAreFloating(stackId) &&
-                getStack(DOCKED_STACK_ID) != null) {
+        if (!allowResizeInDockedMode
+                && !stack.getWindowConfiguration().tasksAreFloating()
+                && getStack(DOCKED_STACK_ID) != null) {
             // If the docked stack exists, don't resize non-floating stacks independently of the
             // size computed from the docked stack size (otherwise they will be out of sync)
             return;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 3bc1b2f..ef4869d 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -473,7 +473,7 @@
     void removeWindowContainer() {
         mService.mStackSupervisor.removeLockedTaskLocked(this);
         mWindowContainerController.removeContainer();
-        if (!StackId.persistTaskBounds(getStackId())) {
+        if (!getWindowConfiguration().persistTaskBounds()) {
             // Reset current bounds for task whose bounds shouldn't be persisted so it uses
             // default configuration the next time it launches.
             updateOverrideConfiguration(null);
@@ -2108,8 +2108,9 @@
         final Configuration newConfig = getOverrideConfiguration();
 
         mFullscreen = bounds == null;
+        final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
         if (mFullscreen) {
-            if (mBounds != null && StackId.persistTaskBounds(mStack.mStackId)) {
+            if (mBounds != null && persistBounds) {
                 mLastNonFullscreenBounds = mBounds;
             }
             mBounds = null;
@@ -2122,7 +2123,7 @@
             } else {
                 mBounds.set(mTmpRect);
             }
-            if (mStack == null || StackId.persistTaskBounds(mStack.mStackId)) {
+            if (mStack == null || persistBounds) {
                 mLastNonFullscreenBounds = mBounds;
             }
             computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
@@ -2242,7 +2243,7 @@
     }
 
     /** Returns the bounds that should be used to launch this task. */
-    Rect getLaunchBounds() {
+    private Rect getLaunchBounds() {
         if (mStack == null) {
             return null;
         }
@@ -2254,7 +2255,7 @@
                 || stackId == FULLSCREEN_WORKSPACE_STACK_ID
                 || (stackId == DOCKED_STACK_ID && !isResizeable())) {
             return isResizeable() ? mStack.mBounds : null;
-        } else if (!StackId.persistTaskBounds(stackId)) {
+        } else if (!getWindowConfiguration().persistTaskBounds()) {
             return mStack.mBounds;
         }
         return mLastNonFullscreenBounds;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 00d387a..7545a10 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -514,7 +514,7 @@
     }
 
     boolean windowsAreFocusable() {
-        return StackId.canReceiveKeys(getTask().mStack.mStackId) || mAlwaysFocusable;
+        return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
     }
 
     AppWindowContainerController getController() {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 6711257..1d3f198 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -110,6 +110,15 @@
         }
     }
 
+    public WindowConfiguration getWindowConfiguration() {
+        return mFullConfiguration.windowConfiguration;
+    }
+
+    /** Returns the windowing mode the configuration container is currently in. */
+    public int getWindowingMode() {
+        return mFullConfiguration.windowConfiguration.getWindowingMode();
+    }
+
     /** Sets the windowing mode for the configuration container. */
     void setWindowingMode(/*@WindowConfiguration.WindowingMode TODO: causes build error...why?*/
             int windowingMode) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c295241..bf1c3f7 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1809,7 +1809,7 @@
         mTmpTaskForResizePointSearchResult.reset();
         for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
             final TaskStack stack = mTaskStackContainers.get(stackNdx);
-            if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
+            if (!stack.getWindowConfiguration().canResizeTask()) {
                 return null;
             }
 
@@ -3373,7 +3373,8 @@
 
         @Override
         void positionChildAt(int position, TaskStack child, boolean includingParents) {
-            if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) {
+            if (child.getWindowConfiguration().isAlwaysOnTop()
+                    && position != POSITION_TOP) {
                 // This stack is always-on-top, override the default behavior.
                 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
 
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 189689b..3f6378a 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 
 import android.app.ActivityManager.StackId;
+import android.app.WindowConfiguration;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Handler;
@@ -282,7 +283,7 @@
             config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null);
             boolean intersectParentBounds = false;
 
-            if (StackId.tasksAreFloating(mStackId)) {
+            if (stack.getWindowConfiguration().tasksAreFloating()) {
                 // Floating tasks should not be resized to the screen's bounds.
 
                 if (mStackId == PINNED_STACK_ID && bounds.width() == mTmpDisplayBounds.width() &&
@@ -359,7 +360,7 @@
                 bounds.height() == displayInfo.logicalHeight)) {
             // If the bounds are fullscreen, return the value of the fullscreen configuration
             return displayContent.getConfiguration().smallestScreenWidthDp;
-        } else if (StackId.tasksAreFloating(mStackId)) {
+        } else if (mContainer.getWindowConfiguration().tasksAreFloating()) {
             // For floating tasks, calculate the smallest width from the bounds of the task
             return (int) (Math.min(bounds.width(), bounds.height()) / density);
         } else {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6349b05..60384f27 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -244,7 +244,7 @@
         // Update task bounds if needed.
         updateDisplayInfo(getDisplayContent());
 
-        if (StackId.windowsAreScaleable(mStack.mStackId)) {
+        if (getWindowConfiguration().windowsAreScaleable()) {
             // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
             // while a resize is pending.
             forceWindowsScaleable(true /* force */);
@@ -572,7 +572,7 @@
         //   from its stack. The stack will take care of task rotation for the other case.
         mTmpRect2.set(mBounds);
 
-        if (!StackId.isTaskResizeAllowed(mStack.mStackId)) {
+        if (!getWindowConfiguration().canResizeTask()) {
             setBounds(mTmpRect2, getOverrideConfiguration());
             return;
         }
@@ -620,7 +620,7 @@
      * we will have a jump at the end.
      */
     boolean isFloating() {
-        return StackId.tasksAreFloating(mStack.mStackId)
+        return getWindowConfiguration().tasksAreFloating()
                 && !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
     }
 
@@ -709,7 +709,7 @@
 
     @Override
     boolean fillsParent() {
-        return mFillsParent || !StackId.isTaskResizeAllowed(mStack.mStackId);
+        return mFillsParent || !getWindowConfiguration().canResizeTask();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 6dbdcc4..8a4a49a 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1439,7 +1439,7 @@
 
     void findTaskForResizePoint(int x, int y, int delta,
             DisplayContent.TaskForResizePointSearchResult results) {
-        if (!StackId.isTaskResizeAllowed(mStackId)) {
+        if (!getWindowConfiguration().canResizeTask()) {
             results.searchDone = true;
             return;
         }
@@ -1636,10 +1636,6 @@
         return false;
     }
 
-    public boolean hasMovementAnimations() {
-        return StackId.hasMovementAnimations(mStackId);
-    }
-
     public boolean isForceScaled() {
         return mBoundsAnimating;
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5a181f1..f7ab534 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1737,7 +1737,7 @@
         if (mToken.okToAnimate()
                 && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
                 && !isDragResizing() && !adjustedForMinimizedDockOrIme
-                && (task == null || getTask().mStack.hasMovementAnimations())
+                && getWindowConfiguration().hasMovementAnimations()
                 && !mWinAnimator.mLastHidden) {
             mWinAnimator.setMoveAnimation(left, top);
         }
@@ -2422,7 +2422,7 @@
      * because we want to preserve its location on screen to be re-activated later when the user
      * interacts with it.
      */
-    boolean shouldKeepVisibleDeadAppWindow() {
+    private boolean shouldKeepVisibleDeadAppWindow() {
         if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) {
             // Not a visible app window or the app isn't dead.
             return false;
@@ -2440,8 +2440,7 @@
             return false;
         }
 
-        final TaskStack stack = getStack();
-        return stack != null && StackId.keepVisibleDeadAppWindowOnScreen(stack.mStackId);
+        return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen();
     }
 
     /** @return true if this window desires key events. */
@@ -3209,7 +3208,7 @@
         // one or more frame to wrong offset. So here we send fullscreen backdrop if either
         // isDragResizing() or isDragResizeChanged() is true.
         boolean resizing = isDragResizing() || isDragResizeChanged();
-        if (StackId.useWindowFrameForBackdrop(getStackId()) || !resizing) {
+        if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) {
             return frame;
         }
         final DisplayInfo displayInfo = getDisplayInfo();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 9d3db7c..906cac6 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -49,6 +49,7 @@
 import static com.android.server.wm.proto.WindowStateAnimatorProto.LAST_CLIP_RECT;
 import static com.android.server.wm.proto.WindowStateAnimatorProto.SURFACE;
 
+import android.app.WindowConfiguration;
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
@@ -1145,7 +1146,7 @@
         final TaskStack stack = w.getTask().mStack;
         stack.getDimBounds(finalClipRect);
 
-        if (StackId.tasksAreFloating(stack.mStackId)) {
+        if (stack.getWindowConfiguration().tasksAreFloating()) {
             w.expandForSurfaceInsets(finalClipRect);
         }
 
@@ -1165,6 +1166,7 @@
             transform.mapRect(finalCrop);
             finalClipRect.top = (int)finalCrop.top;
             finalClipRect.left = (int)finalCrop.left;
+            // TODO: Are the assignments below a mistake?
             finalClipRect.right = (int)finalClipRect.right;
             finalClipRect.bottom = (int)finalClipRect.bottom;
         }
@@ -1324,8 +1326,8 @@
 
         // We need to do some acrobatics with surface position, because their clip region is
         // relative to the inside of the surface, but the stack bounds aren't.
-        if (StackId.hasWindowShadow(stack.mStackId)
-                && !StackId.isTaskResizeAllowed(stack.mStackId)) {
+        final WindowConfiguration winConfig = w.getWindowConfiguration();
+        if (winConfig.hasWindowShadow() && !winConfig.canResizeTask()) {
                 // The windows in this stack display drop shadows and the fill the entire stack
                 // area. Adjust the stack bounds we will use to cropping take into account the
                 // offsets we use to display the drop shadow so it doesn't get cropped.
@@ -1760,8 +1762,7 @@
      * @return Returns true if the surface was successfully shown.
      */
     private boolean showSurfaceRobustlyLocked() {
-        final Task task = mWin.getTask();
-        if (task != null && StackId.windowsAreScaleable(task.mStack.mStackId)) {
+        if (mWin.getWindowConfiguration().windowsAreScaleable()) {
             mSurfaceController.forceScaleableInTransaction(true);
         }