Remove dependency on resizable activity to enter PiP.

- Removing the requirement for activities to have both the
  resizeableActivity and supportsPictureInPicture attribute
  to enter PiP.  The activity may still be resized when
  entering picture-in-picture.

Bug: 34256643
Test: android.server.cts.ActivityManagerPinnedStackTests
Change-Id: If6bd4721c53072e5518f554a8c7598705517c132
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a72950b..28b8d6a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9341,7 +9341,7 @@
         if (tr.mBounds != null) {
             rti.bounds = new Rect(tr.mBounds);
         }
-        rti.isDockable = tr.canGoInDockedStack();
+        rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreen();
         rti.resizeMode = tr.mResizeMode;
 
         ActivityRecord base = null;
@@ -13404,13 +13404,12 @@
             if (supportsMultiWindow || forceResizable) {
                 mSupportsMultiWindow = true;
                 mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
-                mSupportsPictureInPicture = supportsPictureInPicture || forceResizable;
             } else {
                 mSupportsMultiWindow = false;
                 mSupportsFreeformWindowManagement = false;
-                mSupportsPictureInPicture = false;
             }
             mSupportsSplitScreenMultiWindow = supportsSplitScreenMultiWindow;
+            mSupportsPictureInPicture = supportsPictureInPicture;
             mWindowManager.setForceResizableTasks(mForceResizableActivities);
             mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
             // This happens before any activities are started, so we can change global configuration
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 3bd44f5..2a849b6 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -39,7 +39,6 @@
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.os.Build.VERSION_CODES.HONEYCOMB;
@@ -66,7 +65,6 @@
 import android.annotation.NonNull;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
-import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.app.PictureInPictureArgs;
 import android.app.ResultInfo;
@@ -78,7 +76,6 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
@@ -454,6 +451,7 @@
         }
         if (info != null) {
             pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
+            pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
         }
         pw.println(prefix + "supportsPictureInPictureWhilePausing: "
                 + supportsPictureInPictureWhilePausing);
@@ -879,24 +877,50 @@
     }
 
     boolean isResizeable() {
-        return ActivityInfo.isResizeableMode(info.resizeMode);
+        return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
     }
 
-    boolean isResizeableOrForced() {
-        return !isHomeActivity() && (isResizeable() || service.mForceResizableActivities);
-    }
-
-    boolean isNonResizableOrForced() {
+    /**
+     * @return whether this activity is non-resizeable or forced to be resizeable
+     */
+    boolean isNonResizableOrForcedResizable() {
         return info.resizeMode != RESIZE_MODE_RESIZEABLE
-                && info.resizeMode != RESIZE_MODE_RESIZEABLE_AND_PIPABLE
                 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
     }
 
     /**
-     * @return whether this activity's resize mode supports PIP.
+     * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
      */
     boolean supportsPictureInPicture() {
-        return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+        return service.mSupportsPictureInPicture && !isHomeActivity()
+                && info.supportsPictureInPicture();
+    }
+
+    /**
+     * @return whether this activity supports split-screen multi-window and can be put in the docked
+     *         stack.
+     */
+    boolean supportsSplitScreen() {
+        // An activity can not be docked even if it is considered resizeable because it only
+        // supports picture-in-picture mode but has a non-resizeable resizeMode
+        return service.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
+    }
+
+    /**
+     * @return whether this activity supports freeform multi-window and can be put in the freeform
+     *         stack.
+     */
+    boolean supportsFreeform() {
+        return service.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
+    }
+
+    /**
+     * @return whether this activity supports non-PiP multi-window.
+     */
+    private boolean supportsResizeableMultiWindow() {
+        return service.mSupportsMultiWindow && !isHomeActivity()
+                && (ActivityInfo.isResizeableMode(info.resizeMode)
+                        || service.mForceResizableActivities);
     }
 
     /**
@@ -945,10 +969,6 @@
         return false;
     }
 
-    boolean canGoInDockedStack() {
-        return !isHomeActivity() && isResizeableOrForced();
-    }
-
     boolean isAlwaysFocusable() {
         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
     }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 963a9dc..7bfea9a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -62,7 +62,6 @@
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
-import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
 import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
@@ -73,7 +72,6 @@
 import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
 import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
 import static java.lang.Integer.MAX_VALUE;
-import static java.lang.Integer.MIN_VALUE;
 
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -1545,7 +1543,7 @@
             // home task even though it's not resizable.
             final ActivityRecord r = focusedStack.topRunningActivityLocked();
             final TaskRecord task = r != null ? r.task : null;
-            return task == null || task.canGoInDockedStack() || task.isHomeTask() ? STACK_VISIBLE
+            return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
                     : STACK_INVISIBLE;
         }
 
@@ -4665,7 +4663,7 @@
             }
             ci.numActivities = numActivities;
             ci.numRunning = numRunning;
-            ci.isDockable = task.canGoInDockedStack();
+            ci.supportsSplitScreenMultiWindow = task.supportsSplitScreen();
             ci.resizeMode = task.mResizeMode;
             list.add(ci);
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 2c1c3a1..24ff1d7 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -90,7 +90,6 @@
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
 import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static java.lang.Integer.MAX_VALUE;
-import static java.lang.Integer.MIN_VALUE;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -2576,7 +2575,7 @@
             // This means that tasks that were on external displays will be restored on the
             // primary display.
             stackId = task.getLaunchStackId();
-        } else if (stackId == DOCKED_STACK_ID && !task.canGoInDockedStack()) {
+        } else if (stackId == DOCKED_STACK_ID && !task.supportsSplitScreen()) {
             // Preferred stack is the docked stack, but the task can't go in the docked stack.
             // Put it in the fullscreen stack.
             stackId = FULLSCREEN_WORKSPACE_STACK_ID;
@@ -3895,14 +3894,14 @@
         }
 
         final ActivityRecord topActivity = task.getTopActivity();
-        if (!task.canGoInDockedStack() || forceNonResizable) {
+        if (!task.supportsSplitScreen() || forceNonResizable) {
             // Display a warning toast that we tried to put a non-dockable task in the docked stack.
             mService.mTaskChangeNotificationController.notifyActivityDismissingDockedStack();
 
             // Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
             // we need to move it to top of fullscreen stack, otherwise it will be covered.
             moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, actualStackId == DOCKED_STACK_ID);
-        } else if (topActivity != null && topActivity.isNonResizableOrForced()
+        } else if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
                 && !topActivity.noDisplay) {
             String packageName = topActivity.appInfo.packageName;
             mService.mTaskChangeNotificationController.notifyActivityForcedResizable(
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 26d2ee2..8c341a8 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1966,10 +1966,10 @@
                 canUseFocusedStack = true;
                 break;
             case DOCKED_STACK_ID:
-                canUseFocusedStack = r.canGoInDockedStack();
+                canUseFocusedStack = r.supportsSplitScreen();
                 break;
             case FREEFORM_WORKSPACE_STACK_ID:
-                canUseFocusedStack = r.isResizeableOrForced();
+                canUseFocusedStack = r.supportsFreeform();
                 break;
             default:
                 canUseFocusedStack = isDynamicStack(focusedStackId)
@@ -2056,29 +2056,24 @@
     }
 
     boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
-        if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID) {
-            return false;
+        switch (stackId) {
+            case INVALID_STACK_ID:
+            case HOME_STACK_ID:
+                return false;
+            case FULLSCREEN_WORKSPACE_STACK_ID:
+                return true;
+            case FREEFORM_WORKSPACE_STACK_ID:
+                return r.supportsFreeform();
+            case DOCKED_STACK_ID:
+                return r.supportsSplitScreen();
+            case PINNED_STACK_ID:
+                return r.supportsPictureInPicture();
+            case RECENTS_STACK_ID:
+                return r.isRecentsActivity();
+            default:
+                Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
+                return false;
         }
-
-        if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
-                && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
-            return false;
-        }
-
-        if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
-            return true;
-        }
-
-        if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
-            return false;
-        }
-
-        final boolean supportsPip = mService.mSupportsPictureInPicture
-                && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
-        if (stackId == PINNED_STACK_ID && !supportsPip) {
-            return false;
-        }
-        return true;
     }
 
     Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 7b4d289..2373ea8 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -85,6 +85,7 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
@@ -141,6 +142,7 @@
     private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
     private static final String ATTR_CALLING_UID = "calling_uid";
     private static final String ATTR_CALLING_PACKAGE = "calling_package";
+    private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
     private static final String ATTR_RESIZE_MODE = "resize_mode";
     private static final String ATTR_PRIVILEGED = "privileged";
     private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
@@ -188,6 +190,9 @@
 
     int mResizeMode;        // The resize mode of this task and its activities.
                             // Based on the {@link ActivityInfo#resizeMode} of the root activity.
+    boolean mSupportsPictureInPicture;  // Whether or not this task and its activities support PiP.
+            // Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root
+            // activity.
     boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
                                      // changes on a temporary basis.
     private int mLockTaskMode;  // Which tasklock mode to launch this task in. One of
@@ -356,8 +361,9 @@
             boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
             TaskThumbnailInfo lastThumbnailInfo, int taskAffiliation, int prevTaskId,
             int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
-            int resizeMode, boolean privileged, boolean _realActivitySuspended,
-            boolean userSetupComplete, int minWidth, int minHeight) {
+            int resizeMode, boolean supportsPictureInPicture, boolean privileged,
+            boolean _realActivitySuspended, boolean userSetupComplete, int minWidth,
+            int minHeight) {
         mService = service;
         mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
                 TaskPersister.IMAGE_EXTENSION;
@@ -396,6 +402,7 @@
         mCallingUid = callingUid;
         mCallingPackage = callingPackage;
         mResizeMode = resizeMode;
+        mSupportsPictureInPicture = supportsPictureInPicture;
         mPrivileged = privileged;
         mMinWidth = minWidth;
         mMinHeight = minHeight;
@@ -415,8 +422,8 @@
         final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
         final Configuration overrideConfig = getOverrideConfiguration();
         mWindowContainerController = new TaskWindowContainerController(taskId, this, getStackId(),
-                userId, bounds, overrideConfig, mResizeMode, isHomeTask(), isOnTopLauncher(), onTop,
-                showForAllUsers, lastTaskDescription);
+                userId, bounds, overrideConfig, mResizeMode, mSupportsPictureInPicture,
+                isHomeTask(), isOnTopLauncher(), onTop, showForAllUsers, lastTaskDescription);
     }
 
     void removeWindowContainer() {
@@ -691,6 +698,7 @@
             autoRemoveRecents = false;
         }
         mResizeMode = info.resizeMode;
+        mSupportsPictureInPicture = info.supportsPictureInPicture();
         mIsOnTopLauncher = (info.flags & FLAG_ON_TOP_LAUNCHER) != 0;
         mLockTaskMode = info.lockTaskLaunchMode;
         mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
@@ -1301,9 +1309,21 @@
         return mTaskToReturnTo == HOME_ACTIVITY_TYPE;
     }
 
+    private boolean isResizeable(boolean checkSupportsPip) {
+        return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
+                || (checkSupportsPip && mSupportsPictureInPicture)) && !mTemporarilyUnresizable;
+    }
+
     boolean isResizeable() {
-        return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode))
-                && !mTemporarilyUnresizable;
+        return isResizeable(true /* checkSupportsPip */);
+    }
+
+    boolean supportsSplitScreen() {
+        // A task can not be docked even if it is considered resizeable because it only supports
+        // picture-in-picture mode but has a non-resizeable resizeMode
+        return mService.mSupportsSplitScreenMultiWindow
+                && isResizeable(false /* checkSupportsPip */)
+                && !ActivityInfo.isPreserveOrientationMode(mResizeMode);
     }
 
     /**
@@ -1329,11 +1349,6 @@
         return isHomeTask() && mIsOnTopLauncher;
     }
 
-    boolean canGoInDockedStack() {
-        return isResizeable() && mService.mSupportsSplitScreenMultiWindow &&
-                !ActivityInfo.isPreserveOrientationMode(mResizeMode);
-    }
-
     /**
      * Find the activity in the history stack within the given task.  Returns
      * the index within the history at which it's found, or < 0 if not found.
@@ -1482,6 +1497,8 @@
         out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
         out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
         out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
+        out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
+                String.valueOf(mSupportsPictureInPicture));
         out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
         if (mLastNonFullscreenBounds != null) {
             out.attribute(
@@ -1552,6 +1569,7 @@
         int callingUid = -1;
         String callingPackage = "";
         int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
+        boolean supportsPictureInPicture = false;
         boolean privileged = false;
         Rect bounds = null;
         int minWidth = INVALID_MIN_SIZE;
@@ -1618,6 +1636,8 @@
                 callingPackage = attrValue;
             } else if (ATTR_RESIZE_MODE.equals(attrName)) {
                 resizeMode = Integer.parseInt(attrValue);
+            } else if (ATTR_SUPPORTS_PICTURE_IN_PICTURE.equals(attrName)) {
+                supportsPictureInPicture = Boolean.parseBoolean(attrValue);
             } else if (ATTR_PRIVILEGED.equals(attrName)) {
                 privileged = Boolean.parseBoolean(attrValue);
             } else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
@@ -1690,6 +1710,15 @@
             if (taskType == HOME_ACTIVITY_TYPE && resizeMode == RESIZE_MODE_RESIZEABLE) {
                 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
             }
+        } else {
+            // This activity has previously marked itself explicitly as both resizeable and
+            // supporting picture-in-picture.  Since there is no longer a requirement for
+            // picture-in-picture activities to be resizeable, we can mark this simply as
+            // resizeable and supporting picture-in-picture separately.
+            if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
+                resizeMode = RESIZE_MODE_RESIZEABLE;
+                supportsPictureInPicture = true;
+            }
         }
 
         final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
@@ -1697,8 +1726,9 @@
                 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
                 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
                 taskDescription, thumbnailInfo, taskAffiliation, prevTaskId, nextTaskId,
-                taskAffiliationColor, callingUid, callingPackage, resizeMode, privileged,
-                realActivitySuspended, userSetupComplete, minWidth, minHeight);
+                taskAffiliationColor, callingUid, callingPackage, resizeMode,
+                supportsPictureInPicture, privileged, realActivitySuspended, userSetupComplete,
+                minWidth, minHeight);
         task.updateOverrideConfiguration(bounds);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
@@ -2084,6 +2114,7 @@
         pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
         pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
                 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
+                pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
                 pw.print(" isResizeable=" + isResizeable());
                 pw.print(" firstActiveTime=" + lastActiveTime);
                 pw.print(" lastActiveTime=" + lastActiveTime);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3a3ec71..c5ed6ec 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -82,6 +82,10 @@
     // Resize mode of the task. See {@link ActivityInfo#resizeMode}
     private int mResizeMode;
 
+    // Whether the task supports picture-in-picture.
+    // See {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE}
+    private boolean mSupportsPictureInPicture;
+
     // Whether the task is currently being drag-resized
     private boolean mDragResizing;
     private int mDragResizeMode;
@@ -94,14 +98,16 @@
     private TaskDescription mTaskDescription;
 
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
-            Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode, boolean homeTask,
-            TaskDescription taskDescription, TaskWindowContainerController controller) {
+            Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode,
+            boolean supportsPictureInPicture, boolean homeTask, TaskDescription taskDescription,
+            TaskWindowContainerController controller) {
         mTaskId = taskId;
         mStack = stack;
         mUserId = userId;
         mService = service;
         mIsOnTopLauncher = isOnTopLauncher;
         mResizeMode = resizeMode;
+        mSupportsPictureInPicture = supportsPictureInPicture;
         mHomeTask = homeTask;
         setController(controller);
         setBounds(bounds, overrideConfig);
@@ -327,7 +333,8 @@
     }
 
     boolean isResizeable() {
-        return ActivityInfo.isResizeableMode(mResizeMode) || mService.mForceResizableTasks;
+        return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture
+                || mService.mForceResizableTasks;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index 61a2cd9..fbc3389 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -63,8 +63,8 @@
 
     public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
             int stackId, int userId, Rect bounds, Configuration overrideConfig, int resizeMode,
-            boolean homeTask, boolean isOnTopLauncher, boolean toTop, boolean showForAllUsers,
-            TaskDescription taskDescription) {
+            boolean supportsPictureInPicture, boolean homeTask, boolean isOnTopLauncher,
+            boolean toTop, boolean showForAllUsers, TaskDescription taskDescription) {
         super(listener, WindowManagerService.getInstance());
         mTaskId = taskId;
 
@@ -81,7 +81,7 @@
             }
             EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
             final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode,
-                    homeTask, isOnTopLauncher, taskDescription);
+                    supportsPictureInPicture, homeTask, isOnTopLauncher, taskDescription);
             final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
             stack.addTask(task, position, showForAllUsers, true /* moveParents */);
         }
@@ -89,10 +89,10 @@
 
     @VisibleForTesting
     Task createTask(int taskId, TaskStack stack, int userId, Rect bounds,
-            Configuration overrideConfig, int resizeMode, boolean homeTask,
-            boolean isOnTopLauncher, TaskDescription taskDescription) {
+            Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+            boolean homeTask, boolean isOnTopLauncher, TaskDescription taskDescription) {
         return new Task(taskId, stack, userId, mService, bounds, overrideConfig, isOnTopLauncher,
-                resizeMode, homeTask, taskDescription, this);
+                resizeMode, supportsPictureInPicture, homeTask, taskDescription, this);
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 085cfd8..186884b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -77,7 +77,8 @@
         final Rect mInsetBounds = new Rect();
         boolean mFullscreenForTest = true;
         TaskWithBounds(Rect bounds) {
-            super(0, mStubStack, 0, sWm, null, null, false, 0, false, new TaskDescription(), null);
+            super(0, mStubStack, 0, sWm, null, null, false, 0, false, false, new TaskDescription(),
+                    null);
             mBounds = bounds;
         }
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index ae344dd..847f34d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -181,7 +181,7 @@
     /**Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
     static Task createTaskInStack(TaskStack stack, int userId) {
         final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, false, 0,
-                false, new TaskDescription(), null);
+                false, false, new TaskDescription(), null);
         stack.addTask(newTask, POSITION_TOP);
         return newTask;
     }
@@ -238,9 +238,11 @@
 
         TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
                 Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode,
-                boolean homeTask, TaskWindowContainerController controller) {
+                boolean supportsPictureInPicture, boolean homeTask,
+                TaskWindowContainerController controller) {
             super(taskId, stack, userId, service, bounds, overrideConfig, isOnTopLauncher,
-                    resizeMode, homeTask, new TaskDescription(), controller);
+                    resizeMode, supportsPictureInPicture, homeTask, new TaskDescription(),
+                            controller);
         }
 
         boolean shouldDeferRemoval() {
@@ -270,17 +272,18 @@
 
         TestTaskWindowContainerController(int stackId) {
             super(sNextTaskId++, snapshot -> {}, stackId, 0 /* userId */, null /* bounds */,
-                    EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE, false /* homeTask*/,
+                    EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
+                    false /* supportsPictureInPicture */, false /* homeTask*/,
                     false /* isOnTopLauncher */, true /* toTop*/, true /* showForAllUsers */,
                     new TaskDescription());
         }
 
         @Override
         TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
-                Configuration overrideConfig, int resizeMode, boolean homeTask,
-                boolean isOnTopLauncher, TaskDescription taskDescription) {
+                Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+                boolean homeTask, boolean isOnTopLauncher, TaskDescription taskDescription) {
             return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig,
-                    isOnTopLauncher, resizeMode, homeTask, this);
+                    isOnTopLauncher, resizeMode, supportsPictureInPicture, homeTask, this);
         }
     }