Complete removal of Task from DisplayContent.

Moved Tasks into TaskStacks.

Change-Id: I3478dab4eab3a68d4d71a7a5bb2e65ba2394f2d7
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b498b50..bd85b77 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -31,6 +31,7 @@
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.pm.UserManagerService;
 import com.android.server.wm.AppTransition;
+import com.android.server.wm.StackBox;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.Zygote;
@@ -1456,7 +1457,7 @@
 
     public void setWindowManager(WindowManagerService wm) {
         mWindowManager = wm;
-        wm.createStack(HOME_ACTIVITY_STACK, -1, ActivityManager.TASK_STACK_GOES_OVER, 1.0f);
+        wm.createStack(HOME_ACTIVITY_STACK, -1, StackBox.TASK_STACK_GOES_OVER, 1.0f);
     }
 
     public static final Context main(int factoryTest) {
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 548f8b9..0cd3136 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -85,7 +85,7 @@
     /**
      * Sorted most recent at top, oldest at [0].
      */
-    ArrayList<Task> mTasks = new ArrayList<Task>();
+    ArrayList<Task> mTmpTasks = new ArrayList<Task>();
 
     /**
      * @param display May not be null.
@@ -114,7 +114,12 @@
     }
 
     ArrayList<Task> getTasks() {
-        return mTasks;
+        mTmpTasks.clear();
+        int numBoxes = mStackBoxes.size();
+        for (int boxNdx = 0; boxNdx < numBoxes; ++boxNdx) {
+            mTmpTasks.addAll(mStackBoxes.get(boxNdx).getTasks());
+        }
+        return mTmpTasks;
     }
 
     public void updateDisplayInfo() {
@@ -122,9 +127,10 @@
     }
 
     int numTokens() {
+        getTasks();
         int count = 0;
-        for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
-            count += mTasks.get(taskNdx).mAppTokens.size();
+        for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+            count += mTmpTasks.get(taskNdx).mAppTokens.size();
         }
         return count;
     }
@@ -168,18 +174,6 @@
         return newStack;
     }
 
-    boolean addTaskToStack(Task task, int stackId, boolean toTop) {
-        int stackBoxNdx;
-        for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
-            final StackBox box = mStackBoxes.get(stackBoxNdx);
-            if (box.addTaskToStack(task, stackId, toTop)) {
-                layoutNeeded = true;
-                break;
-            }
-        }
-        return false;
-    }
-
     boolean resizeStack(int stackId, float weight) {
         int stackBoxNdx;
         for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
@@ -219,8 +213,9 @@
             if (ndx > 0) {
                 pw.println();
                 pw.println("  Application tokens in Z order:");
-                for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
-                    AppTokenList tokens = mTasks.get(taskNdx).mAppTokens;
+                getTasks();
+                for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                    AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens;
                     for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
                         final AppWindowToken wtoken = tokens.get(tokenNdx);
                         pw.print("  App #"); pw.print(ndx--);
diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java
index 5fd39e3..bd007e5 100644
--- a/services/java/com/android/server/wm/StackBox.java
+++ b/services/java/com/android/server/wm/StackBox.java
@@ -18,6 +18,8 @@
 
 import android.graphics.Rect;
 
+import java.util.ArrayList;
+
 public class StackBox {
     /** For use with {@link WindowManagerService#createStack} */
     public static final int TASK_STACK_GOES_BEFORE = 0;
@@ -36,6 +38,7 @@
     TaskStack mStack;
     Rect mBounds;
     boolean layoutNeeded;
+    ArrayList<Task> mTmpTasks = new ArrayList<Task>();
 
     StackBox(DisplayContent displayContent, Rect bounds) {
         mDisplayContent = displayContent;
@@ -165,6 +168,17 @@
         return false;
     }
 
+    ArrayList<Task> getTasks() {
+        mTmpTasks.clear();
+        if (mStack != null) {
+            mTmpTasks.addAll(mStack.getTasks());
+        } else {
+            mTmpTasks.addAll(mFirst.getTasks());
+            mTmpTasks.addAll(mSecond.getTasks());
+        }
+        return mTmpTasks;
+    }
+
     void absorb(StackBox box) {
         mFirst = box.mFirst;
         mSecond = box.mSecond;
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 72bf1a4..4d34b36 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -35,6 +35,10 @@
         return mDisplayContent;
     }
 
+    ArrayList<Task> getTasks() {
+        return mTasks;
+    }
+
     ArrayList<Task> merge(TaskStack stack) {
         ArrayList<Task> taskLists = stack.mTasks;
         taskLists.addAll(mTasks);
@@ -47,6 +51,16 @@
         mTasks.add(toTop ? mTasks.size() : 0, task);
     }
 
+    void moveTaskToTop(Task task) {
+        mTasks.remove(task);
+        addTask(task, true);
+    }
+
+    void moveTaskToBottom(Task task) {
+        mTasks.remove(task);
+        addTask(task, false);
+    }
+
     boolean removeTask(Task task) {
         mParent.makeDirty();
         if (mTasks.remove(task)) {
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index ec8b379..b2aa8eb 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -174,7 +174,7 @@
     private void updateAppWindowsLocked(int displayId) {
         int i;
         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
-        final ArrayList<Task> tasks = displayContent.mTasks;
+        final ArrayList<Task> tasks = displayContent.getTasks();
         final int numTasks = tasks.size();
         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
@@ -462,7 +462,7 @@
     private void testTokenMayBeDrawnLocked(int displayId) {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).mTasks;
+        final ArrayList<Task> tasks = mService.getDisplayContentLocked(displayId).getTasks();
         final int numTasks = tasks.size();
         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 614a7e4..da82a34 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -182,7 +182,7 @@
     static final boolean DEBUG_INPUT_METHOD = false;
     static final boolean DEBUG_VISIBILITY = false;
     static final boolean DEBUG_WINDOW_MOVEMENT = false;
-    static final boolean DEBUG_TOKEN_MOVEMENT = true;
+    static final boolean DEBUG_TOKEN_MOVEMENT = false;
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_APP_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
@@ -952,7 +952,7 @@
         // order of applications.
         WindowState pos = null;
 
-        final ArrayList<Task> tasks = displayContent.mTasks;
+        final ArrayList<Task> tasks = win.getStack().getTasks();
         int taskNdx;
         int tokenNdx = -1;
         for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -3179,7 +3179,7 @@
                 return;
             }
 
-            final ArrayList<Task> localTasks = displayContent.mTasks;
+            final ArrayList<Task> localTasks = displayContent.getTasks();
             int taskNdx;
             for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
                 AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
@@ -3217,7 +3217,7 @@
             if (taskNdx >= 0 || t >= 0) {
                 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
                 Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager="
-                        + displayContent.mTasks);
+                        + displayContent.getTasks());
                 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
             }
         }
@@ -3379,8 +3379,8 @@
                     throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
                 }
                 task = new Task(atoken, stack);
+                stack.addTask(task, true);
                 mTaskIdToTask.put(taskId, task);
-                task.getDisplayContent().mTasks.add(task);
             } else {
                 task.addAppToken(addPos, atoken);
             }
@@ -3458,17 +3458,16 @@
     }
 
     public int getOrientationFromAppTokensLocked() {
-        int curGroup = 0;
         int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
         boolean findingBehind = false;
-        boolean haveGroup = false;
         boolean lastFullscreen = false;
         // TODO: Multi window.
         DisplayContent displayContent = getDefaultDisplayContentLocked();
-        final ArrayList<Task> tasks = displayContent.mTasks;
+        final ArrayList<Task> tasks = displayContent.getTasks();
         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
-            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+            final int firstToken = tokens.size() - 1;
+            for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
                 final AppWindowToken atoken = tokens.get(tokenNdx);
     
                 if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
@@ -3482,8 +3481,8 @@
                     continue;
                 }
     
-                if (haveGroup == true && curGroup != atoken.groupId) {
-                    // If we have hit a new application group, and the bottom
+                if (tokenNdx == firstToken) {
+                    // If we have hit a new Task, and the bottom
                     // of the previous group didn't explicitly say to use
                     // the orientation behind it, and the last app was
                     // full screen, then we'll stick with the
@@ -3503,9 +3502,8 @@
                     continue;
                 }
     
-                if (!haveGroup) {
-                    haveGroup = true;
-                    curGroup = atoken.groupId;
+                if (tokenNdx == 0) {
+                    // Last token in this task.
                     lastOrientation = atoken.requestedOrientation;
                 }
     
@@ -4404,7 +4402,6 @@
 
                 if (task.removeAppToken(wtoken)) {
                     mTaskIdToTask.delete(wtoken.groupId);
-                    displayContent.mTasks.remove(task);
                 }
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
@@ -4461,7 +4458,7 @@
         while (iterator.hasNext()) {
             DisplayContent displayContent = iterator.next();
             Slog.v(TAG, "  Display " + displayContent.getDisplayId());
-            final ArrayList<Task> tasks = displayContent.mTasks;
+            final ArrayList<Task> tasks = displayContent.getTasks();
             int i = displayContent.numTokens();
             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
                 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
@@ -4590,7 +4587,9 @@
         return index;
     }
 
-    private void moveTaskWindowsLocked(Task task, DisplayContent displayContent) {
+    private void moveTaskWindowsLocked(Task task) {
+        DisplayContent displayContent = task.getDisplayContent();
+
         // First remove all of the windows from the list.
         AppTokenList tokens = task.mAppTokens;
         final int numTokens = tokens.size();
@@ -4634,18 +4633,8 @@
                     Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskIdToTask");
                     return;
                 }
-                DisplayContent displayContent = task.getDisplayContent();
-                if (displayContent == null) {
-                    Slog.e(TAG, "moveTaskToTop: DisplayContent not found for taskId=" + taskId);
-                    return;
-                }
-                ArrayList<Task> tasks = displayContent.getTasks();
-                if (!tasks.remove(task)) {
-                    Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTasks");
-                }
-                tasks.add(task);
-
-                moveTaskWindowsLocked(task, displayContent);
+                task.mStack.moveTaskToTop(task);
+                moveTaskWindowsLocked(task);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -4662,18 +4651,8 @@
                             + " not found in mTaskIdToTask");
                     return;
                 }
-                DisplayContent displayContent = task.getDisplayContent();
-                if (displayContent == null) {
-                    Slog.e(TAG, "moveTaskToBottom: DisplayContent not found for taskId=" + taskId);
-                    return;
-                }
-                ArrayList<Task> tasks = displayContent.getTasks();
-                if (!tasks.remove(task)) {
-                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId + " not found in mTasks");
-                }
-                tasks.add(0, task);
-
-                moveTaskWindowsLocked(task, displayContent);
+                task.mStack.moveTaskToBottom(task);
+                moveTaskWindowsLocked(task);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -7022,7 +7001,7 @@
                     synchronized (mWindowMap) {
                         Slog.w(TAG, "App freeze timeout expired.");
                         DisplayContent displayContent = getDefaultDisplayContentLocked();
-                        final ArrayList<Task> tasks = displayContent.mTasks;
+                        final ArrayList<Task> tasks = displayContent.getTasks();
                         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
                             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
                             for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
@@ -7552,7 +7531,7 @@
         }
 
         // And add in the still active app tokens in Z order.
-        final ArrayList<Task> tasks = displayContent.mTasks;
+        final ArrayList<Task> tasks = displayContent.getTasks();
         final int numTasks = tasks.size();
         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
@@ -8231,7 +8210,7 @@
         mAppTransition.setIdle();
         // Restore window app tokens to the ActivityManager views
         final DisplayContent displayContent = getDefaultDisplayContentLocked();
-        final ArrayList<Task> tasks = displayContent.mTasks;
+        final ArrayList<Task> tasks = displayContent.getTasks();
         final int numTasks = tasks.size();
         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
@@ -8400,7 +8379,7 @@
     private void updateAllDrawnLocked(DisplayContent displayContent) {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        final ArrayList<Task> tasks = displayContent.mTasks;
+        final ArrayList<Task> tasks = displayContent.getTasks();
         final int numTasks = tasks.size();
         for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
             final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
@@ -8904,7 +8883,6 @@
                     final Task task = mTaskIdToTask.get(token.groupId);
                     if (task != null && task.removeAppToken(token)) {
                         mTaskIdToTask.delete(token.groupId);
-                        displayContent.mTasks.remove(task);
                     }
                     exitingAppTokens.remove(i);
                 }
@@ -9342,7 +9320,8 @@
     }
 
     private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
-        final ArrayList<Task> tasks = displayContent.mTasks;
+        // Set nextApp to the first app and set taskNdx and tokenNdx to point to the app following.
+        final ArrayList<Task> tasks = displayContent.getTasks();
         int taskNdx = tasks.size() - 1;
         AppTokenList tokens = taskNdx >= 0 ? tasks.get(taskNdx).mAppTokens : null;
         int tokenNdx = tokens != null ? tokens.size() - 1 : -1;
@@ -9370,8 +9349,8 @@
 
             // If this window's application has been removed, just skip it.
             if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) {
-                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed
-                        ? "removed" : "sendingToBottom"));
+                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + thisApp + " because "
+                        + (thisApp.removed ? "removed" : "sendingToBottom"));
                 continue;
             }
 
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index ca6d2ca..e471e46 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -685,6 +685,13 @@
         return mDisplayContent.getDisplayId();
     }
 
+    TaskStack getStack() {
+        if (mAppToken != null) {
+            return mService.mTaskIdToTask.get(mAppToken.groupId).mStack;
+        }
+        return null;
+    }
+
     public long getInputDispatchingTimeoutNanos() {
         return mAppToken != null
                 ? mAppToken.inputDispatchingTimeoutNanos