Added AM API to remove a stack

Use the new API when closing Pip.

Bug: 26982752
Change-Id: I074d23b5535a4534626183ab77142d3932a803f0
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 6206323..eedb82b 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -167,6 +167,7 @@
                 "       am stack positiontask <TASK_ID> <STACK_ID> <POSITION>\n" +
                 "       am stack list\n" +
                 "       am stack info <STACK_ID>\n" +
+                "       am stack remove <STACK_ID>\n" +
                 "       am task lock <TASK_ID>\n" +
                 "       am task lock stop\n" +
                 "       am task resizeable <TASK_ID> [0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)]\n" +
@@ -324,6 +325,8 @@
                 "\n" +
                 "am stack info: display the information about activity stack <STACK_ID>.\n" +
                 "\n" +
+                "am stack remove: remove stack <STACK_ID>.\n" +
+                "\n" +
                 "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.\n" +
                 "\n" +
                 "am task lock stop: end the current task lock.\n" +
@@ -1732,6 +1735,9 @@
             case "size-docked-stack-test":
                 runStackSizeDockedStackTest();
                 break;
+            case "remove":
+                runStackRemove();
+                break;
             default:
                 showError("Error: unknown command '" + op + "'");
                 break;
@@ -1868,6 +1874,12 @@
         }
     }
 
+    private void runStackRemove() throws Exception {
+        String stackIdStr = nextArgRequired();
+        int stackId = Integer.valueOf(stackIdStr);
+        mAm.removeStack(stackId);
+    }
+
     private void runMoveTopActivityToPinnedStack() throws Exception {
         int stackId = Integer.valueOf(nextArgRequired());
         final Rect bounds = getBounds();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 99852b8..04979ef 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2887,6 +2887,13 @@
             reply.writeNoException();
             return true;
         }
+        case REMOVE_STACK: {
+            data.enforceInterface(IActivityManager.descriptor);
+            final int stackId = data.readInt();
+            removeStack(stackId);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -6747,5 +6754,17 @@
         reply.recycle();
     };
 
+    @Override
+    public void removeStack(int stackId) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(stackId);
+        mRemote.transact(REMOVE_STACK, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 98ce273..ca86c18 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -599,6 +599,8 @@
 
     public void notifyPinnedStackAnimationEnded() throws RemoteException;
 
+    public void removeStack(int stackId) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -975,4 +977,5 @@
     int STOP_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 364;
     int SUPPORTS_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 365;
     int NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 366;
+    int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 3c30410..fac6338 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -205,22 +205,10 @@
     public void closePip() {
         mState = STATE_NO_PIP;
         mPipTaskId = TASK_ID_NO_PIP;
-        StackInfo stackInfo = null;
         try {
-            stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
-            if (stackInfo == null) {
-                return;
-            }
+            mActivityManager.removeStack(PINNED_STACK_ID);
         } catch (RemoteException e) {
-            Log.e(TAG, "getStackInfo failed", e);
-            return;
-        }
-        for (int taskId : stackInfo.taskIds) {
-            try {
-                mActivityManager.removeTask(taskId);
-            } catch (RemoteException e) {
-                Log.e(TAG, "removeTask failed", e);
-            }
+            Log.e(TAG, "removeStack failed", e);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5061901..9b7c672 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9209,11 +9209,35 @@
     }
 
     @Override
-    public boolean removeTask(int taskId) {
+    public void removeStack(int stackId) {
+        enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
+        if (stackId == HOME_STACK_ID) {
+            throw new IllegalArgumentException("Removing home stack is not allowed.");
+        }
+
         synchronized (this) {
-            enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
-                    "removeTask()");
-            long ident = Binder.clearCallingIdentity();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                final ActivityStack stack = mStackSupervisor.getStack(stackId);
+                if (stack == null) {
+                    return;
+                }
+                final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+                for (int i = tasks.size() - 1; i >= 0; i--) {
+                    removeTaskByIdLocked(
+                            tasks.get(i).taskId, true /* killProcess */, REMOVE_FROM_RECENTS);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    @Override
+    public boolean removeTask(int taskId) {
+        enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()");
+        synchronized (this) {
+            final long ident = Binder.clearCallingIdentity();
             try {
                 return removeTaskByIdLocked(taskId, true, REMOVE_FROM_RECENTS);
             } finally {