Ability to getStack by windowingMode/activityType in WM.

Another step away from using static stack ids for things.

Test: Existing tests pass.
Test: go/wm-smoke
Bug: 64146578
Change-Id: I419eca4968ea97bfa6ff71f6e1deaa247abd0328
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2d1fc91..78f8157 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -16,8 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityManager.StackId;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -1312,7 +1311,8 @@
 
                 // Notify the pinned stack upon all windows drawn. If there was an animation in
                 // progress then this signal will resume that animation.
-                final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
+                final TaskStack pinnedStack =
+                        mDisplayContent.getStack(WINDOWING_MODE_PINNED);
                 if (pinnedStack != null) {
                     pinnedStack.onAllWindowsDrawn();
                 }
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index b7b1f7c..dc5a814 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -236,6 +236,28 @@
         return thisType == ACTIVITY_TYPE_UNDEFINED || otherType == ACTIVITY_TYPE_UNDEFINED;
     }
 
+    /**
+     * Returns true if this container is compatible with the input windowing mode and activity type.
+     */
+    public boolean isCompatible(int windowingMode, int activityType) {
+        final int thisActivityType = getActivityType();
+        final int thisWindowingMode = getWindowingMode();
+        final boolean sameActivityType = thisActivityType == activityType;
+        final boolean sameWindowingMode = thisWindowingMode == windowingMode;
+
+        if (sameActivityType && sameWindowingMode) {
+            return true;
+        }
+
+        if (activityType != ACTIVITY_TYPE_UNDEFINED && activityType != ACTIVITY_TYPE_STANDARD) {
+            // Only activity type need to match for non-standard activity types that are defined.
+            return sameActivityType;
+        }
+
+        // Otherwise we are compatible if the windowing mode is the same.
+        return sameWindowingMode;
+    }
+
     public void registerConfigurationChangeListener(ConfigurationContainerListener listener) {
         if (mChangeListeners.contains(listener)) {
             return;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 98a1bd3..7ae5d1a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -19,8 +19,10 @@
 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.HOME_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -117,7 +119,6 @@
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.app.ActivityManager.StackId;
-import android.app.WindowConfiguration;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
@@ -1457,6 +1458,28 @@
         return null;
     }
 
+    /**
+     * Returns the topmost stack on the display that is compatible with the input windowing mode.
+     * Null is no compatible stack on the display.
+     */
+    TaskStack getStack(int windowingMode) {
+        return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
+    }
+
+    /**
+     * Returns the topmost stack on the display that is compatible with the input windowing mode and
+     * activity type. Null is no compatible stack on the display.
+     */
+    private TaskStack getStack(int windowingMode, int activityType) {
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
+            if (stack.isCompatible(windowingMode, activityType)) {
+                return stack;
+            }
+        }
+        return null;
+    }
+
     @VisibleForTesting
     int getStackCount() {
         return mTaskStackContainers.size();
@@ -1501,7 +1524,7 @@
         // If there was no pinned stack, we still need to notify the controller of the display info
         // update as a result of the config change.  We do this here to consolidate the flow between
         // changes when there is and is not a stack.
-        if (getStackById(PINNED_STACK_ID) == null) {
+        if (getStack(WINDOWING_MODE_PINNED) == null) {
             mPinnedStackControllerLocked.onDisplayInfoChanged();
         }
     }
@@ -2238,7 +2261,7 @@
      * @return The docked stack, but only if it is visible, and {@code null} otherwise.
      */
     TaskStack getDockedStackLocked() {
-        final TaskStack stack = getStackById(DOCKED_STACK_ID);
+        final TaskStack stack = getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         return (stack != null && stack.isVisible()) ? stack : null;
     }
 
@@ -2247,7 +2270,7 @@
      * visible.
      */
     TaskStack getDockedStackIgnoringVisibility() {
-        return getStackById(DOCKED_STACK_ID);
+        return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
     }
 
     /** Find the visible, touch-deliverable window under the given point */
@@ -3421,11 +3444,11 @@
                     : requestedPosition >= topChildPosition;
             int targetPosition = requestedPosition;
 
-            if (toTop && stack.mStackId != PINNED_STACK_ID
-                    && getStackById(PINNED_STACK_ID) != null) {
+            if (toTop && stack.getWindowingMode() != WINDOWING_MODE_PINNED
+                    && getStack(WINDOWING_MODE_PINNED) != null) {
                 // The pinned stack is always the top most stack (always-on-top) when it is present.
                 TaskStack topStack = mChildren.get(topChildPosition);
-                if (topStack.mStackId != PINNED_STACK_ID) {
+                if (topStack.getWindowingMode() != WINDOWING_MODE_PINNED) {
                     throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
                 }
 
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 030b986..e0a4666 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -17,8 +17,9 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.StackId.DOCKED_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.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.Surface.ROTATION_270;
@@ -456,7 +457,8 @@
             boolean isHomeStackResizable) {
         long animDuration = 0;
         if (animate) {
-            final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID);
+            final TaskStack stack =
+                    mDisplayContent.getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
             final long transitionDuration = isAnimationMaximizing()
                     ? mService.mAppTransition.getLastClipRevealTransitionDuration()
                     : DEFAULT_APP_TRANSITION_DURATION;
@@ -605,8 +607,8 @@
         if (mMinimizedDock && mService.mPolicy.isKeyguardShowingAndNotOccluded()) {
             return;
         }
-        final TaskStack fullscreenStack =
-                mDisplayContent.getStackById(FULLSCREEN_WORKSPACE_STACK_ID);
+        final TaskStack fullscreenStack = mDisplayContent.getStack(
+                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
         final boolean homeBehind = fullscreenStack != null && fullscreenStack.isVisible();
         setMinimizedDockedStack(homeVisible && !homeBehind, animate);
@@ -801,7 +803,8 @@
     }
 
     private boolean animateForMinimizedDockedStack(long now) {
-        final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID);
+        final TaskStack stack =
+                mDisplayContent.getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         if (!mAnimationStarted) {
             mAnimationStarted = true;
             mAnimationStartTime = now;
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 1e7140a..4c9326db 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.util.TypedValue.COMPLEX_UNIT_DIP;
 
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -404,27 +405,29 @@
      */
     private void notifyMovementBoundsChanged(boolean fromImeAdjustement) {
         synchronized (mService.mWindowMap) {
-            if (mPinnedStackListener != null) {
-                try {
-                    final Rect insetBounds = new Rect();
-                    getInsetBounds(insetBounds);
-                    final Rect normalBounds = getDefaultBounds();
-                    if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
-                        transformBoundsToAspectRatio(normalBounds, mAspectRatio,
-                                false /* useCurrentMinEdgeSize */);
-                    }
-                    final Rect animatingBounds = mTmpAnimatingBoundsRect;
-                    final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
-                    if (pinnedStack != null) {
-                        pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
-                    } else {
-                        animatingBounds.set(normalBounds);
-                    }
-                    mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
-                            animatingBounds, fromImeAdjustement, mDisplayInfo.rotation);
-                } catch (RemoteException e) {
-                    Slog.e(TAG_WM, "Error delivering actions changed event.", e);
+            if (mPinnedStackListener == null) {
+                return;
+            }
+            try {
+                final Rect insetBounds = new Rect();
+                getInsetBounds(insetBounds);
+                final Rect normalBounds = getDefaultBounds();
+                if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
+                    transformBoundsToAspectRatio(normalBounds, mAspectRatio,
+                            false /* useCurrentMinEdgeSize */);
                 }
+                final Rect animatingBounds = mTmpAnimatingBoundsRect;
+                final TaskStack pinnedStack =
+                        mDisplayContent.getStack(WINDOWING_MODE_PINNED);
+                if (pinnedStack != null) {
+                    pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
+                } else {
+                    animatingBounds.set(normalBounds);
+                }
+                mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
+                        animatingBounds, fromImeAdjustement, mDisplayInfo.rotation);
+            } catch (RemoteException e) {
+                Slog.e(TAG_WM, "Error delivering actions changed event.", e);
             }
         }
     }