Introduce WINDOWING_MODE_MULTI_WINDOW

Generic multi-window with no presentation attribution from the wm-core.
Needed for wm-shell to correctly drive multi-window cases like Bubbles
and n-way-split.
Current windowing modes split and freeform will probably be migrated to
this once wm-shell drives their presentation.

Test: N/A
Bug: 139371701
Change-Id: I5247f41b4f67d21b2bb5929a52e8ec93c41644c2
diff --git a/api/test-current.txt b/api/test-current.txt
index 3bf2a85..4592b24 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -481,6 +481,7 @@
     field public static final int WINDOWING_MODE_FREEFORM = 5; // 0x5
     field public static final int WINDOWING_MODE_FULLSCREEN = 1; // 0x1
     field public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = 4; // 0x4
+    field public static final int WINDOWING_MODE_MULTI_WINDOW = 6; // 0x6
     field public static final int WINDOWING_MODE_PINNED = 2; // 0x2
     field public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3; // 0x3
     field public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4; // 0x4
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 1e4f8f3..6b40890 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -50,7 +50,7 @@
     /**
      * bounds that can differ from app bounds, which may include things such as insets.
      *
-     * TODO: Investigate combining with {@link mAppBounds}. Can the latter be a product of the
+     * TODO: Investigate combining with {@link #mAppBounds}. Can the latter be a product of the
      * former?
      */
     private Rect mBounds = new Rect();
@@ -87,6 +87,7 @@
     /** Always on-top (always visible). of other siblings in its parent container. */
     public static final int WINDOWING_MODE_PINNED = 2;
     /** The primary container driving the screen to be in split-screen mode. */
+    // TODO: Remove once split-screen is migrated to wm-shell.
     public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3;
     /**
      * The containers adjacent to the {@link #WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} container in
@@ -97,6 +98,7 @@
      * mode
      * @see #WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
      */
+    // TODO: Remove once split-screen is migrated to wm-shell.
     public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4;
     /**
      * Alias for {@link #WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} that makes it clear that the usage
@@ -104,15 +106,20 @@
      * will launch into fullscreen or split-screen secondary depending on if the device is currently
      * in fullscreen mode or split-screen mode.
      */
+    // TODO: Remove once split-screen is migrated to wm-shell.
     public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY =
             WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
     /** Can be freely resized within its parent container. */
+    // TODO: Remove once freeform is migrated to wm-shell.
     public static final int WINDOWING_MODE_FREEFORM = 5;
+    /** Generic multi-window with no presentation attribution from the window manager. */
+    public static final int WINDOWING_MODE_MULTI_WINDOW = 6;
 
     /** @hide */
     @IntDef(prefix = { "WINDOWING_MODE_" }, value = {
             WINDOWING_MODE_UNDEFINED,
             WINDOWING_MODE_FULLSCREEN,
+            WINDOWING_MODE_MULTI_WINDOW,
             WINDOWING_MODE_PINNED,
             WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
             WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
@@ -669,7 +676,7 @@
      * @hide
      */
     public boolean hasWindowShadow() {
-        return tasksAreFloating();
+        return mWindowingMode != WINDOWING_MODE_MULTI_WINDOW && tasksAreFloating();
     }
 
     /**
@@ -688,7 +695,8 @@
      * @hide
      */
     public boolean canResizeTask() {
-        return mWindowingMode == WINDOWING_MODE_FREEFORM;
+        return mWindowingMode == WINDOWING_MODE_FREEFORM
+                || mWindowingMode == WINDOWING_MODE_MULTI_WINDOW;
     }
 
     /** Returns true if the task bounds should persist across power cycles.
@@ -738,8 +746,9 @@
      * @hide
      */
     public boolean isAlwaysOnTop() {
-        return mWindowingMode == WINDOWING_MODE_PINNED
-                || (mWindowingMode == WINDOWING_MODE_FREEFORM && mAlwaysOnTop == ALWAYS_ON_TOP_ON);
+        return mWindowingMode == WINDOWING_MODE_PINNED || (mAlwaysOnTop == ALWAYS_ON_TOP_ON
+                && (mWindowingMode == WINDOWING_MODE_FREEFORM
+                    || mWindowingMode == WINDOWING_MODE_MULTI_WINDOW));
     }
 
     /**
@@ -797,6 +806,7 @@
         switch (windowingMode) {
             case WINDOWING_MODE_UNDEFINED: return "undefined";
             case WINDOWING_MODE_FULLSCREEN: return "fullscreen";
+            case WINDOWING_MODE_MULTI_WINDOW: return "multi-window";
             case WINDOWING_MODE_PINNED: return "pinned";
             case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return "split-screen-primary";
             case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return "split-screen-secondary";
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 9f13718..e28b1e2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -73,6 +73,8 @@
     public static final int WINDOWING_MODE_UNDEFINED = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
     public static final int WINDOWING_MODE_FULLSCREEN =
             WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+    public static final int WINDOWING_MODE_MULTI_WINDOW =
+            WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
     public static final int WINDOWING_MODE_PINNED = WindowConfiguration.WINDOWING_MODE_PINNED;
     public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY =
             WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 1c010c7..9d54255 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -8,6 +8,7 @@
 import static android.app.WaitResult.LAUNCH_STATE_WARM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -119,6 +120,7 @@
     private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
     private static final int WINDOW_STATE_FREEFORM = 2;
     private static final int WINDOW_STATE_ASSISTANT = 3;
+    private static final int WINDOW_STATE_MULTI_WINDOW = 4;
     private static final int WINDOW_STATE_INVALID = -1;
 
     /**
@@ -420,6 +422,9 @@
             case WINDOWING_MODE_FREEFORM:
                 mWindowState = WINDOW_STATE_FREEFORM;
                 break;
+            case WINDOWING_MODE_MULTI_WINDOW:
+                mWindowState = WINDOW_STATE_MULTI_WINDOW;
+                break;
             default:
                 if (windowingMode != WINDOWING_MODE_UNDEFINED) {
                     throw new IllegalStateException("Unknown windowing mode for stack=" + stack
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 62dd7bb..2efd8d1 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -28,6 +28,7 @@
 import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -1979,7 +1980,9 @@
             return false;
         }
         final int windowingMode = getWindowingMode();
-        return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED;
+        return windowingMode != WINDOWING_MODE_FREEFORM
+                && windowingMode != WINDOWING_MODE_PINNED
+                && windowingMode != WINDOWING_MODE_MULTI_WINDOW;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 5a5c102..a2cb3f4 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -25,6 +25,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -6034,6 +6035,10 @@
             return false;
         }
 
+        if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
+            return true;
+        }
+
         final int displayWindowingMode = getWindowingMode();
         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {