Merge "Incremental repairs to side by side stacks."
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 5f5c337..95343f9 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -100,7 +100,7 @@
                 "       am to-intent-uri [INTENT]\n" +
                 "       am switch-user <USER_ID>\n" +
                 "       am stop-user <USER_ID>\n" +
-                "       am stack create <RELATIVE_STACK_ID> <POSITION> <WEIGHT>\n" +
+                "       am stack create <TASK_ID> <RELATIVE_STACK_ID> <POSITION> <WEIGHT>\n" +
                 "       am stack movetask <STACK_ID> <TASK_ID> [true|false]\n" +
                 "       am stack dump\n" +
                 "\n" +
@@ -186,6 +186,7 @@
                 "  code until a later explicit switch to it.\n" +
                 "\n" +
                 "am stack create: create a new stack relative to an existing one.\n" +
+                "   <TASK_ID>: the task to populate the new stack with. Must exist.\n" +
                 "   <RELATIVE_STACK_ID>: existing stack's id.\n" +
                 "   <POSITION>: 0: to left of, 1: to right of, 2: above, 3: below\n" +
                 "   <WEIGHT>: float between 0.2 and 0.8 inclusive.\n" +
@@ -1454,6 +1455,8 @@
     }
 
     private void runStackCreate() throws Exception {
+        String taskIdStr = nextArgRequired();
+        int taskId = Integer.valueOf(taskIdStr);
         String relativeToStr = nextArgRequired();
         int relativeTo = Integer.valueOf(relativeToStr);
         String positionStr = nextArgRequired();
@@ -1462,8 +1465,8 @@
         float weight = Float.valueOf(weightStr);
 
         try {
-            int stackId = mAm.createStack(relativeTo, position, weight);
-            System.out.println("createStack returned " + stackId + "\n\n");
+            int stackId = mAm.createStack(taskId, relativeTo, position, weight);
+            System.out.println("createStack returned new stackId=" + stackId + "\n\n");
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b089e2a..94f4db2 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -107,7 +107,8 @@
     public ActivityManagerNative() {
         attachInterface(this, descriptor);
     }
-    
+
+    @Override
     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
             throws RemoteException {
         switch (code) {
@@ -197,7 +198,7 @@
             Intent intent = Intent.CREATOR.createFromParcel(data);
             String resolvedType = data.readString();
             IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();    
+            String resultWho = data.readString();
             int requestCode = data.readInt();
             int startFlags = data.readInt();
             Configuration config = Configuration.CREATOR.createFromParcel(data);
@@ -223,7 +224,7 @@
             }
             String resolvedType = data.readString();
             IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();    
+            String resultWho = data.readString();
             int requestCode = data.readInt();
             int flagsMask = data.readInt();
             int flagsValues = data.readInt();
@@ -236,7 +237,7 @@
             reply.writeInt(result);
             return true;
         }
-        
+
         case START_NEXT_MATCHING_ACTIVITY_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -267,7 +268,7 @@
         case FINISH_SUB_ACTIVITY_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            String resultWho = data.readString();    
+            String resultWho = data.readString();
             int requestCode = data.readInt();
             finishSubActivity(token, resultWho, requestCode);
             reply.writeNoException();
@@ -478,14 +479,13 @@
             IThumbnailReceiver receiver = receiverBinder != null
                 ? IThumbnailReceiver.Stub.asInterface(receiverBinder)
                 : null;
-            List list = getTasks(maxNum, fl, receiver);
+            List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl, receiver);
             reply.writeNoException();
             int N = list != null ? list.size() : -1;
             reply.writeInt(N);
             int i;
             for (i=0; i<N; i++) {
-                ActivityManager.RunningTaskInfo info =
-                        (ActivityManager.RunningTaskInfo)list.get(i);
+                ActivityManager.RunningTaskInfo info = list.get(i);
                 info.writeToParcel(reply, 0);
             }
             return true;
@@ -535,14 +535,13 @@
             data.enforceInterface(IActivityManager.descriptor);
             int maxNum = data.readInt();
             int fl = data.readInt();
-            List list = getServices(maxNum, fl);
+            List<ActivityManager.RunningServiceInfo> list = getServices(maxNum, fl);
             reply.writeNoException();
             int N = list != null ? list.size() : -1;
             reply.writeInt(N);
             int i;
             for (i=0; i<N; i++) {
-                ActivityManager.RunningServiceInfo info =
-                        (ActivityManager.RunningServiceInfo)list.get(i);
+                ActivityManager.RunningServiceInfo info = list.get(i);
                 info.writeToParcel(reply, 0);
             }
             return true;
@@ -555,7 +554,7 @@
             reply.writeTypedList(list);
             return true;
         }
-        
+
         case GET_RUNNING_APP_PROCESSES_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             List<ActivityManager.RunningAppProcessInfo> list = getRunningAppProcesses();
@@ -611,10 +610,11 @@
 
         case CREATE_STACK_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
-            int position = data.readInt();
+            int taskId = data.readInt();
             int relativeStackId = data.readInt();
+            int position = data.readInt();
             float weight = data.readFloat();
-            int res = createStack(position, relativeStackId, weight);
+            int res = createStack(taskId, relativeStackId, position, weight);
             reply.writeNoException();
             reply.writeInt(res);
             return true;
@@ -1071,9 +1071,9 @@
             reply.writeInt(res);
             return true;
         }
-        
+
         case CLEAR_APP_DATA_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);            
+            data.enforceInterface(IActivityManager.descriptor);
             String packageName = data.readString();
             IPackageDataObserver observer = IPackageDataObserver.Stub.asInterface(
                     data.readStrongBinder());
@@ -1083,7 +1083,7 @@
             reply.writeInt(res ? 1 : 0);
             return true;
         }
-        
+
         case GRANT_URI_PERMISSION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder b = data.readStrongBinder();
@@ -1095,7 +1095,7 @@
             reply.writeNoException();
             return true;
         }
-        
+
         case REVOKE_URI_PERMISSION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder b = data.readStrongBinder();
@@ -1106,7 +1106,7 @@
             reply.writeNoException();
             return true;
         }
-        
+
         case SHOW_WAITING_FOR_DEBUGGER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder b = data.readStrongBinder();
@@ -1295,7 +1295,7 @@
             reply.writeNoException();
             return true;
         }
-        
+
         case FORCE_STOP_PACKAGE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String packageName = data.readString();
@@ -2595,13 +2595,15 @@
         reply.recycle();
     }
     @Override
-    public int createStack(int position, int relativeStackId, float weight) throws RemoteException
+    public int createStack(int taskId, int relativeStackId, int position, float weight)
+            throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(position);
+        data.writeInt(taskId);
         data.writeInt(relativeStackId);
+        data.writeInt(position);
         data.writeFloat(weight);
         mRemote.transact(CREATE_STACK_TRANSACTION, data, reply, 0);
         reply.readException();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c52a35a..46c97d6 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -115,7 +115,8 @@
     public void moveTaskToBack(int task) throws RemoteException;
     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
     public void moveTaskBackwards(int task) throws RemoteException;
-    public int createStack(int relativeStackId, int position, float weight) throws RemoteException;
+    public int createStack(int taskId, int relativeStackId, int position, float weight)
+            throws RemoteException;
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
     public void resizeStack(int stackId, float weight) throws RemoteException;
     public List<StackInfo> getStacks() throws RemoteException;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 52b933f..a3bb823 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6265,13 +6265,16 @@
     }
 
     @Override
-    public int createStack(int relativeStackId, int position, float weight) {
+    public int createStack(int taskId, int relativeStackId, int position, float weight) {
         synchronized (this) {
             if (mStackSupervisor.getStack(relativeStackId) == null) {
                 return -1;
             }
             int stackId = mStackSupervisor.createStack();
             mWindowManager.createStack(stackId, relativeStackId, position, weight);
+            if (taskId > 0) {
+                moveTaskToStack(taskId, stackId, true);
+            }
             return stackId;
         }
     }
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 7b8ad43..8768688 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -236,13 +236,10 @@
         final ActivityStack stack = task.stack;
         if (stack.removeTask(task) && !stack.isHomeStack()) {
             mStacks.remove(stack);
-            final int oldStackId = stack.mStackId;
-            final int newMainStackId = mService.mWindowManager.removeStack(oldStackId);
-            if (newMainStackId == HOME_STACK_ID) {
-                return;
-            }
-            if (mMainStack.mStackId == oldStackId) {
-                mMainStack = getStack(newMainStackId);
+            final int stackId = stack.mStackId;
+            final int nextStackId = mService.mWindowManager.removeStack(stackId);
+            if (mMainStack.mStackId == stackId) {
+                mMainStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
             }
         }
     }
@@ -1044,8 +1041,8 @@
         if (!r.isHomeActivity) {
             if (mStacks.size() == 1) {
                 // Time to create the first app stack.
-                int stackId =
-                        mService.createStack(HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
+                int stackId = mService.createStack(-1, HOME_STACK_ID,
+                        StackBox.TASK_STACK_GOES_OVER, 1.0f);
                 mMainStack = getStack(stackId);
             }
             return mMainStack;
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index edf3d3b..915c696c 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -90,11 +90,12 @@
     /** True when the home StackBox is at the top of mStackBoxes, false otherwise */
     private TaskStack mHomeStack = null;
 
-    /**
-     * Sorted most recent at top, oldest at [0].
-     */
+    /** Save allocating when retrieving tasks */
     ArrayList<Task> mTmpTasks = new ArrayList<Task>();
 
+    /** Sorted most recent at top, oldest at [0]. */
+    ArrayList<TaskStack> mStackHistory = new ArrayList<TaskStack>();
+
     /**
      * @param display May not be null.
      */
@@ -125,17 +126,23 @@
         return mStackBoxes.get(0).mStack != mHomeStack;
     }
 
+    void moveStack(TaskStack stack, boolean toTop) {
+        mStackHistory.remove(stack);
+        mStackHistory.add(toTop ? mStackHistory.size() : 0, stack);
+    }
+
     /**
-     * Retrieve the tasks on this display in stack order from the topmost TaskStack down.
-     * Note that the order of TaskStacks in the same StackBox is defined within StackBox.
+     * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
      * @return All the Tasks, in order, on this display.
      */
     ArrayList<Task> getTasks() {
         mTmpTasks.clear();
-        int numBoxes = mStackBoxes.size();
-        for (int boxNdx = 0; boxNdx < numBoxes; ++boxNdx) {
-            mTmpTasks.addAll(mStackBoxes.get(boxNdx).getTasks());
+        final int numStacks = mStackHistory.size();
+        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks());
         }
+        if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" +
+                mStackHistory);
         return mTmpTasks;
     }
 
@@ -221,6 +228,13 @@
         return false;
     }
 
+    void addStackBox(StackBox box, boolean toTop) {
+        if (mStackBoxes.size() >= 2) {
+            throw new RuntimeException("addStackBox: Too many toplevel StackBoxes!");
+        }
+        mStackBoxes.add(toTop ? mStackBoxes.size() : 0, box);
+    }
+
     void removeStackBox(StackBox box) {
         if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box);
         final TaskStack stack = box.mStack;
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index d966001..cacc723 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -31,7 +31,6 @@
 import android.view.KeyEvent;
 import android.view.WindowManager;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 
 final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
@@ -68,6 +67,7 @@
      * 
      * Called by the InputManager.
      */
+    @Override
     public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
         if (inputWindowHandle == null) {
             return;
@@ -87,6 +87,7 @@
      * 
      * Called by the InputManager.
      */
+    @Override
     public long notifyANR(InputApplicationHandle inputApplicationHandle,
             InputWindowHandle inputWindowHandle) {
         AppWindowToken appWindowToken = null;
@@ -163,10 +164,20 @@
     }
 
     private void addInputWindowHandleLw(final InputWindowHandle inputWindowHandle,
-            final WindowState child, final int flags, final int type,
+            final WindowState child, int flags, final int type,
             final boolean isVisible, final boolean hasFocus, final boolean hasWallpaper) {
         // Add a window to our list of input windows.
         inputWindowHandle.name = child.toString();
+        final boolean modal = (flags & (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) == 0;
+        if (modal && child.mAppToken != null) {
+            // Limit the outer touch to the activity stack region.
+            flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+            inputWindowHandle.touchableRegion.set(child.getStackBounds());
+        } else {
+            // Not modal or full screen modal
+            child.getTouchableRegion(inputWindowHandle.touchableRegion);
+        }
         inputWindowHandle.layoutParamsFlags = flags;
         inputWindowHandle.layoutParamsType = type;
         inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
@@ -195,7 +206,6 @@
             inputWindowHandle.scaleFactor = 1;
         }
 
-        child.getTouchableRegion(inputWindowHandle.touchableRegion);
 
         addInputWindowHandleLw(inputWindowHandle);
     }
@@ -259,10 +269,10 @@
                 // Skip this window because it cannot possibly receive input.
                 continue;
             }
-            
+
             final int flags = child.mAttrs.flags;
             final int type = child.mAttrs.type;
-            
+
             final boolean hasFocus = (child == mInputFocus);
             final boolean isVisible = child.isVisibleLw();
             final boolean hasWallpaper = (child == mService.mWallpaperTarget)
diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java
index bcc5137..b195f0b 100644
--- a/services/java/com/android/server/wm/StackBox.java
+++ b/services/java/com/android/server/wm/StackBox.java
@@ -42,7 +42,7 @@
 
     /** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this
      * is this entire size of mDisplayContent. */
-    final StackBox mParent;
+    StackBox mParent;
 
     /** First child, this is null exactly when mStack is non-null. */
     StackBox mFirst;
@@ -105,13 +105,14 @@
         return mFirst.contains(stackId) || mSecond.contains(stackId);
     }
 
-    /** Determine if the specified stack is the first child or second child. Presumes that this
-     * is called on mParent of the specified stack.
-     * @param stack the stack to determine.
-     * @return true if stack is the first child.
+    /** Determine if this StackBox is the first child or second child.
+     * @return true if this is the first child.
      */
-    boolean isFirstChild(TaskStack stack) {
-        return mFirst.mStack == stack;
+    boolean isFirstChild() {
+        if (mParent == null) {
+            return false;
+        }
+        return mParent.mFirst == this;
     }
 
     /** Returns the bounds of the specified TaskStack if it is contained in this StackBox.
@@ -217,15 +218,6 @@
         return mTmpTasks;
     }
 
-    /** Combine a child StackBox into its parent.
-     * @param child The surviving child to be merge up into this StackBox. */
-    void absorb(StackBox child) {
-        mFirst = child.mFirst;
-        mSecond = child.mSecond;
-        mStack = child.mStack;
-        layoutNeeded = true;
-    }
-
     /** Return the stackId of the first mFirst StackBox with a non-null mStack */
     int getStackId() {
         if (mStack != null) {
@@ -236,18 +228,33 @@
 
     /** Remove this box and propagate its sibling's content up to their parent.
      * @return The first stackId of the resulting StackBox. */
-    int removeStack() {
+    int remove() {
+        if (mStack != null) {
+            mDisplayContent.mStackHistory.remove(mStack);
+        }
+        mDisplayContent.layoutNeeded = true;
+
         if (mParent == null) {
+            // This is the top-plane stack.
             mDisplayContent.removeStackBox(this);
             return HOME_STACK_ID;
         }
-        if (mParent.mFirst == this) {
-            mParent.absorb(mParent.mSecond);
+
+        StackBox sibling = isFirstChild() ? mParent.mSecond : mParent.mFirst;
+        StackBox grandparent = mParent.mParent;
+        if (grandparent == null) {
+            // mParent is a top-plane stack. Now sibling will be.
+            mDisplayContent.removeStackBox(mParent);
+            mDisplayContent.addStackBox(sibling, true);
         } else {
-            mParent.absorb(mParent.mFirst);
+            sibling.mParent = grandparent;
+            if (mParent.isFirstChild()) {
+                grandparent.mFirst = sibling;
+            } else {
+                grandparent.mSecond = sibling;
+            }
         }
-        mParent.makeDirty();
-        return mParent.getStackId();
+        return sibling.getStackId();
     }
 
     boolean resize(int stackId, float weight) {
@@ -255,7 +262,7 @@
             return mFirst.resize(stackId, weight) || mSecond.resize(stackId, weight);
         }
         if (mStack.mStackId == stackId) {
-            mParent.mWeight = mParent.isFirstChild(mStack) ? weight : 1.0f - weight;
+            mParent.mWeight = isFirstChild() ? weight : 1.0f - weight;
             return true;
         }
         return false;
diff --git a/services/java/com/android/server/wm/Task.java b/services/java/com/android/server/wm/Task.java
index 2520f31..88eb96e 100644
--- a/services/java/com/android/server/wm/Task.java
+++ b/services/java/com/android/server/wm/Task.java
@@ -47,6 +47,6 @@
 
     @Override
     public String toString() {
-        return "taskId=" + taskId + " appTokens=" + mAppTokens;
+        return "{taskId=" + taskId + " appTokens=" + mAppTokens + "}";
     }
 }
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 1c49e7d..590849f 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -92,7 +92,7 @@
     }
 
     int remove() {
-        return mStackBox.removeStack();
+        return mStackBox.remove();
     }
 
     int numTokens() {
@@ -109,4 +109,9 @@
             pw.print(prefix); pw.println(mTasks.get(taskNdx));
         }
     }
+
+    @Override
+    public String toString() {
+        return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
+    }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a00fb7b..da28cd8 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3383,6 +3383,7 @@
                 }
                 task = new Task(atoken, stack);
                 stack.addTask(task, true);
+                stack.getDisplayContent().moveStack(stack, true);
                 mTaskIdToTask.put(taskId, task);
             } else {
                 task.addAppToken(addPos, atoken);
@@ -3703,6 +3704,8 @@
                     Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
                     return;
                 }
+                Task task = mTaskIdToTask.get(newFocus.groupId);
+                task.getDisplayContent().moveStack(task.mStack, true);
                 changed = mFocusedApp != newFocus;
                 mFocusedApp = newFocus;
                 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp
@@ -4675,6 +4678,7 @@
                     displayContent.moveHomeStackBox(true);
                 }
                 stack.moveTaskToTop(task);
+                displayContent.moveStack(stack, true);
                 moveTaskWindowsLocked(task);
             }
         } finally {
@@ -4694,6 +4698,7 @@
                 }
                 task.mStack.moveTaskToBottom(task);
                 moveTaskWindowsLocked(task);
+                task.getDisplayContent().moveStack(task.mStack, false);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -4721,15 +4726,22 @@
                         "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
                         STACK_WEIGHT_MAX + ", weight=" + weight);
             }
-            final TaskStack relativeStack = mStackIdToStack.get(relativeStackId);
-            DisplayContent displayContent = relativeStack != null ?
-                    relativeStack.getDisplayContent() : getDefaultDisplayContentLocked();
-            TaskStack stack = displayContent.createStack(stackId, relativeStackId, position,
-                    weight);
-            if (stack != null) {
-                mStackIdToStack.put(stackId, stack);
-                performLayoutAndPlaceSurfacesLocked();
+            final DisplayContent displayContent;
+            if (stackId != HOME_STACK_ID) {
+                // TODO: What to do for the first stack on a non-default display?
+                final TaskStack relativeStack = mStackIdToStack.get(relativeStackId);
+                if (relativeStack == null) {
+                    throw new IllegalArgumentException("createStack: Invalid relativeStackId=" +
+                            relativeStackId);
+                }
+                displayContent = relativeStack.getDisplayContent();
+            } else {
+                displayContent = getDefaultDisplayContentLocked();
             }
+            TaskStack stack =
+                    displayContent.createStack(stackId, relativeStackId, position, weight);
+            mStackIdToStack.put(stackId, stack);
+            displayContent.moveStack(stack, true);
         }
     }
 
@@ -4748,10 +4760,15 @@
     public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
         synchronized (mWindowMap) {
             Task task = mTaskIdToTask.get(taskId);
+            if (task == null) {
+                return;
+            }
             task.mStack.removeTask(task);
-            TaskStack newStack = mStackIdToStack.get(stackId);
-            newStack.addTask(task, toTop);
-            newStack.getDisplayContent().layoutNeeded = true;
+
+            TaskStack stack = mStackIdToStack.get(stackId);
+            stack.addTask(task, toTop);
+            stack.getDisplayContent().layoutNeeded = true;
+
             performLayoutAndPlaceSurfacesLocked();
         }
     }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 8be424b..905f55d 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -442,8 +442,7 @@
 
         final int type = mAttrs.type;
         if (mAppToken != null) {
-            StackBox stack = mService.mTaskIdToTask.get(mAppToken.groupId).mStack.mStackBox;
-            mContainingFrame.set(stack.mBounds);
+            mContainingFrame.set(getStackBounds());
         } else {
             mContainingFrame.set(pf);
         }
@@ -704,6 +703,14 @@
         return null;
     }
 
+    Rect getStackBounds() {
+        TaskStack stack = getStack();
+        if (stack != null) {
+            return stack.mStackBox.mBounds;
+        }
+        return mFrame;
+    }
+
     public long getInputDispatchingTimeoutNanos() {
         return mAppToken != null
                 ? mAppToken.inputDispatchingTimeoutNanos