Expose new binder call createStackOnDisplay()

Creates a new, empty ActivityStack on a display. Use the binder call to
launch an activity on said stack.

Bug: 19001243
Change-Id: I0f04e8f2703bcc706f58e75333869fb35f6b1ee9
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 507770c..2a0ed90 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -1694,11 +1694,10 @@
         Intent intent = makeIntent(UserHandle.USER_CURRENT);
 
         try {
-            IBinder homeActivityToken = mAm.getHomeActivityToken();
-            IActivityContainer container =
-                    mAm.createVirtualActivityContainer(homeActivityToken, null);
-            container.attachToDisplay(displayId);
-            container.startActivity(intent);
+            IActivityContainer container = mAm.createStackOnDisplay(displayId);
+            if (container != null) {
+                container.startActivity(intent);
+            }
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 5ecf9ee..88dbbd9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2202,6 +2202,20 @@
             return true;
         }
 
+        case CREATE_STACK_ON_DISPLAY: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int displayId = data.readInt();
+            IActivityContainer activityContainer = createStackOnDisplay(displayId);
+            reply.writeNoException();
+            if (activityContainer != null) {
+                reply.writeInt(1);
+                reply.writeStrongBinder(activityContainer.asBinder());
+            } else {
+                reply.writeInt(0);
+            }
+            return true;
+        }
+
         case GET_ACTIVITY_CONTAINER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder activityToken = data.readStrongBinder();
@@ -5231,6 +5245,25 @@
         reply.recycle();
     }
 
+    public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(displayId);
+        mRemote.transact(CREATE_STACK_ON_DISPLAY, data, reply, 0);
+        reply.readException();
+        final int result = reply.readInt();
+        final IActivityContainer res;
+        if (result == 1) {
+            res = IActivityContainer.Stub.asInterface(reply.readStrongBinder());
+        } else {
+            res = null;
+        }
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index adedbcc..f152c6f 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -436,6 +436,8 @@
     public IActivityContainer createVirtualActivityContainer(IBinder parentActivityToken,
             IActivityContainerCallback callback) throws RemoteException;
 
+    public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException;
+
     public void deleteActivityContainer(IActivityContainer container) throws RemoteException;
 
     public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
@@ -797,4 +799,5 @@
 
     // Start of M transactions
     int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
+    int CREATE_STACK_ON_DISPLAY = IBinder.FIRST_CALL_TRANSACTION+281;
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b1b2421..a2f5c15 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8114,6 +8114,20 @@
     }
 
     @Override
+    public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException {
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "createStackOnDisplay()");
+        synchronized (this) {
+            final int stackId = mStackSupervisor.getNextStackId();
+            final ActivityStack stack = mStackSupervisor.createStackOnDisplay(stackId, displayId);
+            if (stack == null) {
+                return null;
+            }
+            return stack.mActivityContainer;
+        }
+    }
+
+    @Override
     public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
             throws RemoteException {
         synchronized (this) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 27f8312..ba2f449 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1569,10 +1569,9 @@
             }
 
             // Need to create an app stack for this user.
-            int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
+            mFocusedStack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
             if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
-                    " stackId=" + stackId);
-            mFocusedStack = getStack(stackId);
+                    " stackId=" + mFocusedStack.mStackId);
             return mFocusedStack;
         }
         return mHomeStack;
@@ -2592,16 +2591,16 @@
         }
     }
 
-    private int createStackOnDisplay(int stackId, int displayId) {
+    ActivityStack createStackOnDisplay(int stackId, int displayId) {
         ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
         if (activityDisplay == null) {
-            return -1;
+            return null;
         }
 
         ActivityContainer activityContainer = new ActivityContainer(stackId);
         mActivityContainers.put(stackId, activityContainer);
         activityContainer.attachToDisplayLocked(activityDisplay);
-        return stackId;
+        return activityContainer.mStack;
     }
 
     int getNextStackId() {
@@ -2638,7 +2637,7 @@
             // We couldn't find a stack to restore the task to. Possible if are restoring recents
             // before an application stack is created...Go ahead and create one on the default
             // display.
-            stack = getStack(createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY));
+            stack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
             // Restore home stack to top.
             moveHomeStack(true);
             if (DEBUG_RECENTS)