Remove AppTokenIterator from DisplayContent.

Simplify accessing successive AppWindowTokens from different
TaskLists.

Change-Id: Icf6265dd6c7953c9c770c97e1342f0f81256c017
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index a2f3372..3cac4e5 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -945,21 +945,20 @@
             }
         }
     }
-    
+
+    @Override
     public String toString() {
         if (stringName != null) {
-            return stringName;
+            return stringName + " t" + task.taskId + "}";
         }
         StringBuilder sb = new StringBuilder(128);
         sb.append("ActivityRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
-        sb.append(" t");
-        sb.append(task.taskId);
         sb.append(" u");
         sb.append(userId);
         sb.append(' ');
         sb.append(intent.getComponent().flattenToShortString());
-        sb.append('}');
-        return stringName = sb.toString();
+        stringName = sb.toString();
+        return toString();
     }
 }
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 6aae202..33b7a5d 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -16,17 +16,12 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.WindowManagerService.FORWARD_ITERATOR;
-import static com.android.server.wm.WindowManagerService.REVERSE_ITERATOR;
-
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
 
 class DisplayContentList extends ArrayList<DisplayContent> {
 }
@@ -91,8 +86,6 @@
     ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>();
     SparseArray<TaskList> mTaskIdToTaskList = new SparseArray<TaskList>();
 
-    private final AppTokenIterator mTmpAppIterator = new AppTokenIterator();
-
     /**
      * @param display May not be null.
      */
@@ -174,94 +167,12 @@
         wtoken.groupId = newTaskId;
     }
 
-    /**
-     * Return the utility iterator so we don't have to construct new iterators every time we
-     * iterate.
-     * NOTE: Do not ever nest this call or you will have a bad time!
-     * @param reverse Direction of iterator.
-     * @return The utility iterator.
-     */
-    AppTokenIterator getTmpAppIterator(boolean reverse) {
-        mTmpAppIterator.reset(reverse);
-        return mTmpAppIterator;
-    }
-
-    class AppTokenIterator implements Iterator<AppWindowToken> {
-        boolean mReverse;
-        int mTasksNdx;
-        int mActivityNdx;
-        TaskList mTaskList;
-
-        public AppTokenIterator() {
-            this(FORWARD_ITERATOR);
+    int numTokens() {
+        int count = 0;
+        for (int taskNdx = mTaskLists.size() - 1; taskNdx >= 0; --taskNdx) {
+            count += mTaskLists.get(taskNdx).mAppTokens.size();
         }
-
-        public AppTokenIterator(boolean reverse) {
-            reset(reverse);
-        }
-
-        void reset(boolean reverse) {
-            mReverse = reverse;
-            mTasksNdx = reverse ? mTaskLists.size() - 1 : 0;
-            getNextTaskList();
-        }
-
-        private void getNextTaskList() {
-            if (mReverse) {
-                if (mTasksNdx >= 0) {
-                    mTaskList = mTaskLists.get(mTasksNdx);
-                    --mTasksNdx;
-                    mActivityNdx = mTaskList.mAppTokens.size() - 1;
-                }
-            } else {
-                if (mTasksNdx < mTaskLists.size()) {
-                    mTaskList = mTaskLists.get(mTasksNdx);
-                    ++mTasksNdx;
-                    mActivityNdx = 0;
-                }
-            }
-        }
-
-        @Override
-        public boolean hasNext() {
-            if (mTaskList == null) {
-                return false;
-            }
-            if (mReverse) {
-                return mActivityNdx >= 0;
-            }
-            return mActivityNdx < mTaskList.mAppTokens.size();
-        }
-
-        @Override
-        public AppWindowToken next() {
-            if (hasNext()) {
-                AppWindowToken wtoken = mTaskList.mAppTokens.get(mActivityNdx);
-                mActivityNdx += mReverse ? -1 : 1;
-                if (!hasNext()) {
-                    getNextTaskList();
-                }
-                return wtoken;
-            }
-            throw new NoSuchElementException();
-        }
-
-        @Override
-        public void remove() {
-            throw new IllegalArgumentException();
-        }
-
-        int size() {
-            int size = 0;
-            for (int i = mTaskLists.size() - 1; i >= 0; --i) {
-                size += mTaskLists.get(i).mAppTokens.size();
-            }
-            return size;
-        }
-
-        @Override public String toString() {
-            return mTaskLists.toString();
-        }
+        return count;
     }
 
     public void dump(String prefix, PrintWriter pw) {
@@ -288,16 +199,18 @@
             pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
             pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
             pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
-            AppTokenIterator iterator = getTmpAppIterator(REVERSE_ITERATOR);
-            int ndx = iterator.size() - 1;
-            if (ndx >= 0) {
+            int ndx = numTokens();
+            if (ndx > 0) {
                 pw.println();
                 pw.println("  Application tokens in Z order:");
-                while (iterator.hasNext()) {
-                    AppWindowToken wtoken = iterator.next();
-                    pw.print("  App #"); pw.print(ndx--);
-                            pw.print(' '); pw.print(wtoken); pw.println(":");
-                    wtoken.dump(pw, "    ");
+                for (int taskNdx = mTaskLists.size() - 1; taskNdx >= 0; --taskNdx) {
+                    AppTokenList tokens = mTaskLists.get(taskNdx).mAppTokens;
+                    for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                        final AppWindowToken wtoken = tokens.get(tokenNdx);
+                        pw.print("  App #"); pw.print(ndx--);
+                                pw.print(' '); pw.print(wtoken); pw.println(":");
+                        wtoken.dump(pw, "    ");
+                    }
                 }
             }
             if (mExitingTokens.size() > 0) {
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 67daf75..aa81941 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -10,8 +10,6 @@
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
-import static com.android.server.wm.WindowManagerService.FORWARD_ITERATOR;
-import static com.android.server.wm.WindowManagerService.REVERSE_ITERATOR;
 
 import android.content.Context;
 import android.os.Debug;
@@ -23,12 +21,10 @@
 import android.util.TimeUtils;
 import android.util.TypedValue;
 import android.view.Display;
-import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 
-import com.android.server.wm.DisplayContent.AppTokenIterator;
 import com.android.server.wm.WindowManagerService.DisplayContentsIterator;
 import com.android.server.wm.WindowManagerService.LayoutFields;
 
@@ -178,19 +174,24 @@
     private void updateAppWindowsLocked(int displayId) {
         int i;
         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
-        while (iterator.hasNext()) {
-            final AppWindowAnimator appAnimator = iterator.next().mAppAnimator;
-            final boolean wasAnimating = appAnimator.animation != null
-                    && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
-            if (appAnimator.stepAnimationLocked(mCurrentTime)) {
-                mAnimating = true;
-            } else if (wasAnimating) {
-                // stopped animating, do one more pass through the layout
-                setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                        "appToken " + appAnimator.mAppToken + " done");
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
-                        "updateWindowsApps...: done animating " + appAnimator.mAppToken);
+        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+        final int numTasks = tasks.size();
+        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+            final int numTokens = tokens.size();
+            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
+                final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
+                final boolean wasAnimating = appAnimator.animation != null
+                        && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
+                if (appAnimator.stepAnimationLocked(mCurrentTime)) {
+                    mAnimating = true;
+                } else if (wasAnimating) {
+                    // stopped animating, do one more pass through the layout
+                    setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+                            "appToken " + appAnimator.mAppToken + " done");
+                    if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
+                            "updateWindowsApps...: done animating " + appAnimator.mAppToken);
+                }
             }
         }
 
@@ -461,36 +462,40 @@
     private void testTokenMayBeDrawnLocked(int displayId) {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        AppTokenIterator iterator =
-                mService.getDisplayContentLocked(displayId).getTmpAppIterator(FORWARD_ITERATOR);
-        while (iterator.hasNext()) {
-            AppWindowToken wtoken = iterator.next();
-            AppWindowAnimator appAnimator = wtoken.mAppAnimator;
-            final boolean allDrawn = wtoken.allDrawn;
-            if (allDrawn != appAnimator.allDrawn) {
-                appAnimator.allDrawn = allDrawn;
-                if (allDrawn) {
-                    // The token has now changed state to having all
-                    // windows shown...  what to do, what to do?
-                    if (appAnimator.freezingScreen) {
-                        appAnimator.showAllWindowsLocked();
-                        mService.unsetAppFreezingScreenLocked(wtoken, false, true);
-                        if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
-                                "Setting mOrientationChangeComplete=true because wtoken "
-                                + wtoken + " numInteresting=" + wtoken.numInterestingWindows
-                                + " numDrawn=" + wtoken.numDrawnWindows);
-                        // This will set mOrientationChangeComplete and cause a pass through layout.
-                        setAppLayoutChanges(appAnimator,
-                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                                "testTokenMayBeDrawnLocked: freezingScreen");
-                    } else {
-                        setAppLayoutChanges(appAnimator,
-                                WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
-                                "testTokenMayBeDrawnLocked");
-
-                        // We can now show all of the drawn windows!
-                        if (!mService.mOpeningApps.contains(wtoken)) {
-                            mAnimating |= appAnimator.showAllWindowsLocked();
+        final ArrayList<TaskList> tasks = mService.getDisplayContentLocked(displayId).mTaskLists;
+        final int numTasks = tasks.size();
+        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+            final int numTokens = tokens.size();
+            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
+                final AppWindowToken wtoken = tokens.get(tokenNdx);
+                AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+                final boolean allDrawn = wtoken.allDrawn;
+                if (allDrawn != appAnimator.allDrawn) {
+                    appAnimator.allDrawn = allDrawn;
+                    if (allDrawn) {
+                        // The token has now changed state to having all
+                        // windows shown...  what to do, what to do?
+                        if (appAnimator.freezingScreen) {
+                            appAnimator.showAllWindowsLocked();
+                            mService.unsetAppFreezingScreenLocked(wtoken, false, true);
+                            if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
+                                    "Setting mOrientationChangeComplete=true because wtoken "
+                                    + wtoken + " numInteresting=" + wtoken.numInterestingWindows
+                                    + " numDrawn=" + wtoken.numDrawnWindows);
+                            // This will set mOrientationChangeComplete and cause a pass through layout.
+                            setAppLayoutChanges(appAnimator,
+                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
+                                    "testTokenMayBeDrawnLocked: freezingScreen");
+                        } else {
+                            setAppLayoutChanges(appAnimator,
+                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
+                                    "testTokenMayBeDrawnLocked");
+    
+                            // We can now show all of the drawn windows!
+                            if (!mService.mOpeningApps.contains(wtoken)) {
+                                mAnimating |= appAnimator.showAllWindowsLocked();
+                            }
                         }
                     }
                 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 086da37..90ac0b8 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -58,7 +58,6 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
-import com.android.server.wm.DisplayContent.AppTokenIterator;
 
 import android.Manifest;
 import android.app.ActivityManagerNative;
@@ -833,10 +832,14 @@
 
     private void placeWindowBefore(WindowState pos, WindowState window) {
         final WindowList windows = pos.getWindowList();
-        final int i = windows.indexOf(pos);
+        int i = windows.indexOf(pos);
         if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
             + i + " of " + windows.size() + " (before " + pos + ")");
+        if (i < 0) {
+            Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
+            i = 0;
+        }
         windows.add(i, window);
         mWindowsChanged = true;
     }
@@ -951,19 +954,36 @@
                     // Figure out where the window should go, based on the
                     // order of applications.
                     WindowState pos = null;
-                    AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-                    while (iterator.hasNext()) {
-                        AppWindowToken t = iterator.next();
-                        if (t == token) {
-                            break;
-                        }
 
-                        // We haven't reached the token yet; if this token
-                        // is not going to the bottom and has windows on this display, we can
-                        // use it as an anchor for when we do reach the token.
-                        tokenWindowList = getTokenWindowsOnDisplay(t, win.mDisplayContent);
-                        if (!t.sendingToBottom && tokenWindowList.size() > 0) {
-                            pos = tokenWindowList.get(0);
+                    final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+                    int taskNdx;
+                    int tokenNdx = -1;
+                    for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                        AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                        for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                            final AppWindowToken t = tokens.get(tokenNdx);
+                            if (t == token) {
+                                --tokenNdx;
+                                if (tokenNdx < 0) {
+                                    --taskNdx;
+                                    if (taskNdx >= 0) {
+                                        tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
+                                    }
+                                }
+                                break;
+                            }
+
+                            // We haven't reached the token yet; if this token
+                            // is not going to the bottom and has windows on this display, we can
+                            // use it as an anchor for when we do reach the token.
+                            tokenWindowList = getTokenWindowsOnDisplay(t, win.mDisplayContent);
+                            if (!t.sendingToBottom && tokenWindowList.size() > 0) {
+                                pos = tokenWindowList.get(0);
+                            }
+                        }
+                        if (tokenNdx >= 0) {
+                            // early exit
+                            break;
                         }
                     }
                     // We now know the index into the apps.  If we found
@@ -987,12 +1007,19 @@
                     } else {
                         // Continue looking down until we find the first
                         // token that has windows on this display.
-                        while (iterator.hasNext()) {
-                            AppWindowToken t = iterator.next();
-                            tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
-                            final int NW = tokenWindowList.size();
-                            if (NW > 0) {
-                                pos = tokenWindowList.get(NW-1);
+                        for ( ; taskNdx >= 0; --taskNdx) {
+                            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                            for ( ; tokenNdx >= 0; --tokenNdx) {
+                                final AppWindowToken t = tokens.get(tokenNdx);
+                                tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
+                                final int NW = tokenWindowList.size();
+                                if (NW > 0) {
+                                    pos = tokenWindowList.get(NW-1);
+                                    break;
+                                }
+                            }
+                            if (tokenNdx >= 0) {
+                                // found
                                 break;
                             }
                         }
@@ -3128,12 +3155,12 @@
                 return;
             }
 
-            boolean mismatch = false;
-            AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-            for ( ; t >= 0 && !mismatch; --t) {
+            final ArrayList<TaskList> localTasks = displayContent.mTaskLists;
+            int taskNdx;
+            for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
+                AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
                 task = tasks.get(t);
                 List<IApplicationToken> tokens = task.tokens;
-                int v = task.tokens.size() - 1;
 
                 DisplayContent lastDisplayContent = displayContent;
                 displayContent = mTaskIdToDisplayContents.get(taskId);
@@ -3142,26 +3169,31 @@
                     return;
                 }
 
-                while (v >= 0) {
-                    if (!iterator.hasNext()) {
-                        mismatch = true;
-                        break;
-                    }
-                    AppWindowToken atoken = iterator.next();
+                int tokenNdx;
+                int v;
+                for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
+                        tokenNdx >= 0 && v >= 0; ) {
+                    final AppWindowToken atoken = localTokens.get(tokenNdx);
                     if (atoken.removed) {
+                        --tokenNdx;
                         continue;
                     }
                     if (tokens.get(v) != atoken.token) {
-                        mismatch = true;
                         break;
                     }
+                    --tokenNdx;
                     v--;
                 }
+
+                if (tokenNdx >= 0 || v >= 0) {
+                    break;
+                }
             }
 
-            if (mismatch || iterator.hasNext()) {
+            if (taskNdx >= 0 || t >= 0) {
                 Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
-                Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + iterator);
+                Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager="
+                        + displayContent.mTaskLists);
                 Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
             }
         }
@@ -3399,68 +3431,71 @@
         boolean lastFullscreen = false;
         // TODO: Multi window.
         DisplayContent displayContent = getDefaultDisplayContentLocked();
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-        while (iterator.hasNext()) {
-            AppWindowToken atoken = iterator.next();
-
-            if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
-
-            // if we're about to tear down this window and not seek for
-            // the behind activity, don't use it for orientation
-            if (!findingBehind
-                    && (!atoken.hidden && atoken.hiddenRequested)) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
-                        + " -- going to hide");
-                continue;
-            }
-
-            if (haveGroup == true && curGroup != atoken.groupId) {
-                // If we have hit a new application group, 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
-                // user's orientation.
-                if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
-                        && lastFullscreen) {
-                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
-                            + " -- end of group, return " + lastOrientation);
-                    return lastOrientation;
+        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+        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 AppWindowToken atoken = tokens.get(tokenNdx);
+    
+                if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
+    
+                // if we're about to tear down this window and not seek for
+                // the behind activity, don't use it for orientation
+                if (!findingBehind
+                        && (!atoken.hidden && atoken.hiddenRequested)) {
+                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
+                            + " -- going to hide");
+                    continue;
                 }
+    
+                if (haveGroup == true && curGroup != atoken.groupId) {
+                    // If we have hit a new application group, 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
+                    // user's orientation.
+                    if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
+                            && lastFullscreen) {
+                        if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
+                                + " -- end of group, return " + lastOrientation);
+                        return lastOrientation;
+                    }
+                }
+    
+                // We ignore any hidden applications on the top.
+                if (atoken.hiddenRequested || atoken.willBeHidden) {
+                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
+                            + " -- hidden on top");
+                    continue;
+                }
+    
+                if (!haveGroup) {
+                    haveGroup = true;
+                    curGroup = atoken.groupId;
+                    lastOrientation = atoken.requestedOrientation;
+                }
+    
+                int or = atoken.requestedOrientation;
+                // If this application is fullscreen, and didn't explicitly say
+                // to use the orientation behind it, then just take whatever
+                // orientation it has and ignores whatever is under it.
+                lastFullscreen = atoken.appFullscreen;
+                if (lastFullscreen
+                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
+                            + " -- full screen, return " + or);
+                    return or;
+                }
+                // If this application has requested an explicit orientation,
+                // then use it.
+                if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
+                            + " -- explicitly set, return " + or);
+                    return or;
+                }
+                findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
             }
-
-            // We ignore any hidden applications on the top.
-            if (atoken.hiddenRequested || atoken.willBeHidden) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
-                        + " -- hidden on top");
-                continue;
-            }
-
-            if (!haveGroup) {
-                haveGroup = true;
-                curGroup = atoken.groupId;
-                lastOrientation = atoken.requestedOrientation;
-            }
-
-            int or = atoken.requestedOrientation;
-            // If this application is fullscreen, and didn't explicitly say
-            // to use the orientation behind it, then just take whatever
-            // orientation it has and ignores whatever is under it.
-            lastFullscreen = atoken.appFullscreen;
-            if (lastFullscreen
-                    && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
-                        + " -- full screen, return " + or);
-                return or;
-            }
-            // If this application has requested an explicit orientation,
-            // then use it.
-            if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
-                    && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
-                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
-                        + " -- explicitly set, return " + or);
-                return or;
-            }
-            findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
         }
         if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
         return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -4387,10 +4422,14 @@
         while (iterator.hasNext()) {
             DisplayContent displayContent = iterator.next();
             Slog.v(TAG, "  Display " + displayContent.getDisplayId());
-            AppTokenIterator appIterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-            int i = appIterator.size();
-            while (appIterator.hasNext()) {
-                Slog.v(TAG, "  #" + --i + ": " + appIterator.next().token);
+            final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+            int i = displayContent.numTokens();
+            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 AppWindowToken wtoken = tokens.get(tokenNdx);
+                    Slog.v(TAG, "  #" + --i + ": " + wtoken.token);
+                }
             }
         }
     }
@@ -4414,42 +4453,49 @@
         final WindowList windows = displayContent.getWindowList();
         final int NW = windows.size();
 
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-        while (iterator.hasNext()) {
-            if (iterator.next() == target) {
-                break;
-            }
-        }
-
-        while (iterator.hasNext()) {
-            // Find the first app token below the new position that has
-            // a window displayed.
-            final AppWindowToken wtoken = iterator.next();
-            if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
-            if (wtoken.sendingToBottom) {
-                if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
+        boolean found = false;
+        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+            final TaskList task = tasks.get(taskNdx);
+            if (!found && task.taskId != taskId) {
                 continue;
             }
-            for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
-                WindowState win = wtoken.windows.get(i);
-                for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
-                    WindowState cwin = win.mChildWindows.get(j);
-                    if (cwin.mSubLayer >= 0) {
+            AppTokenList tokens = task.mAppTokens;
+            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                final AppWindowToken wtoken = tokens.get(tokenNdx);
+                if (!found && wtoken == target) {
+                    found = true;
+                }
+                if (found) {
+                    // Find the first app token below the new position that has
+                    // a window displayed.
+                    if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
+                    if (wtoken.sendingToBottom) {
+                        if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
+                        continue;
+                    }
+                    for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
+                        WindowState win = wtoken.windows.get(i);
+                        for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
+                            WindowState cwin = win.mChildWindows.get(j);
+                            if (cwin.mSubLayer >= 0) {
+                                for (int pos = NW - 1; pos >= 0; pos--) {
+                                    if (windows.get(pos) == cwin) {
+                                        if (DEBUG_REORDER) Slog.v(TAG,
+                                                "Found child win @" + (pos + 1));
+                                        return pos + 1;
+                                    }
+                                }
+                            }
+                        }
                         for (int pos = NW - 1; pos >= 0; pos--) {
-                            if (windows.get(pos) == cwin) {
-                                if (DEBUG_REORDER) Slog.v(TAG,
-                                        "Found child win @" + (pos + 1));
+                            if (windows.get(pos) == win) {
+                                if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
                                 return pos + 1;
                             }
                         }
                     }
                 }
-                for (int pos = NW - 1; pos >= 0; pos--) {
-                    if (windows.get(pos) == win) {
-                        if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
-                        return pos + 1;
-                    }
-                }
             }
         }
 
@@ -6905,13 +6951,15 @@
                     synchronized (mWindowMap) {
                         Slog.w(TAG, "App freeze timeout expired.");
                         DisplayContent displayContent = getDefaultDisplayContentLocked();
-                        AppTokenIterator iterator =
-                                displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-                        while (iterator.hasNext()) {
-                            AppWindowToken tok = iterator.next();
-                            if (tok.mAppAnimator.freezingScreen) {
-                                Slog.w(TAG, "Force clearing freeze: " + tok);
-                                unsetAppFreezingScreenLocked(tok, true, true);
+                        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+                        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                                AppWindowToken tok = tokens.get(tokenNdx);
+                                if (tok.mAppAnimator.freezingScreen) {
+                                    Slog.w(TAG, "Force clearing freeze: " + tok);
+                                    unsetAppFreezingScreenLocked(tok, true, true);
+                                }
                             }
                         }
                     }
@@ -7433,9 +7481,15 @@
         }
 
         // And add in the still active app tokens in Z order.
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
-        while (iterator.hasNext()) {
-            i = reAddAppWindowsLocked(displayContent, i, iterator.next());
+        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+        final int numTasks = tasks.size();
+        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+            final int numTokens = tokens.size();
+            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
+                final AppWindowToken wtoken = tokens.get(tokenNdx);
+                i = reAddAppWindowsLocked(displayContent, i, wtoken);
+            }
         }
 
         i -= lastBelow;
@@ -8106,9 +8160,15 @@
         mAppTransition.setIdle();
         // Restore window app tokens to the ActivityManager views
         final DisplayContent displayContent = getDefaultDisplayContentLocked();
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
-        while (iterator.hasNext()) {
-            iterator.next().sendingToBottom = false;
+        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+        final int numTasks = tasks.size();
+        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+            final int numTokens = tokens.size();
+            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
+                final AppWindowToken wtoken = tokens.get(tokenNdx);
+                wtoken.sendingToBottom = false;
+            }
         }
         rebuildAppWindowListLocked();
 
@@ -8269,17 +8329,22 @@
     private void updateAllDrawnLocked(DisplayContent displayContent) {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
-        while (iterator.hasNext()) {
-            AppWindowToken wtoken = iterator.next();
-            if (!wtoken.allDrawn) {
-                int numInteresting = wtoken.numInterestingWindows;
-                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
-                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
-                            "allDrawn: " + wtoken
-                            + " interesting=" + numInteresting
-                            + " drawn=" + wtoken.numDrawnWindows);
-                    wtoken.allDrawn = true;
+        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+        final int numTasks = tasks.size();
+        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+            final int numTokens = tokens.size();
+            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
+                final AppWindowToken wtoken = tokens.get(tokenNdx);
+                if (!wtoken.allDrawn) {
+                    int numInteresting = wtoken.numInterestingWindows;
+                    if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
+                        if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                                "allDrawn: " + wtoken
+                                + " interesting=" + numInteresting
+                                + " drawn=" + wtoken.numDrawnWindows);
+                        wtoken.allDrawn = true;
+                    }
                 }
             }
         }
@@ -9202,8 +9267,19 @@
     }
 
     private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-        WindowToken nextApp = iterator.hasNext() ? iterator.next() : null;
+        final ArrayList<TaskList> tasks = displayContent.mTaskLists;
+        int taskNdx = tasks.size() - 1;
+        AppTokenList tokens = taskNdx >= 0 ? tasks.get(taskNdx).mAppTokens : null;
+        int tokenNdx = tokens != null ? tokens.size() - 1 : -1;
+        WindowToken nextApp = tokenNdx >= 0 ? tokens.get(tokenNdx) : null;
+        --tokenNdx;
+        if (tokenNdx < 0) {
+            --taskNdx;
+            if (taskNdx >= 0) {
+                tokens = tasks.get(taskNdx).mAppTokens;
+                tokenNdx = tokens.size() - 1;
+            }
+        }
 
         final WindowList windows = displayContent.getWindowList();
         for (int i = windows.size() - 1; i >= 0; i--) {
@@ -9230,16 +9306,24 @@
             if (thisApp != null && nextApp != null && thisApp != nextApp
                     && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
                 final WindowToken origAppToken = nextApp;
-                while (iterator.hasNext()) {
-                    if (nextApp == mFocusedApp) {
-                        // Whoops, we are below the focused app...  no focus
-                        // for you!
-                        if (localLOGV || DEBUG_FOCUS) Slog.v(
-                            TAG, "Reached focused app: " + mFocusedApp);
-                        return null;
+                final int origTaskNdx = taskNdx;
+                final int origTokenNdx = tokenNdx;
+                for ( ; taskNdx >= 0; --taskNdx) {
+                    tokens = tasks.get(taskNdx).mAppTokens;
+                    for ( ; tokenNdx >= 0; --tokenNdx) {
+                        if (nextApp == mFocusedApp) {
+                            // Whoops, we are below the focused app...  no focus
+                            // for you!
+                            if (localLOGV || DEBUG_FOCUS) Slog.v(
+                                TAG, "Reached focused app: " + mFocusedApp);
+                            return null;
+                        }
+                        nextApp = tokens.get(tokenNdx);
+                        if (nextApp == thisApp) {
+                            break;
+                        }
                     }
-                    nextApp = iterator.next();
-                    if (nextApp == thisApp) {
+                    if (thisApp == nextApp) {
                         break;
                     }
                 }
@@ -9248,13 +9332,9 @@
                     // happen, but if it does we can get totally hosed...
                     // so restart at the original app.
                     nextApp = origAppToken;
-                    iterator = displayContent.new AppTokenIterator(true);
-                    while (iterator.hasNext()) {
-                        // return iterator to same place.
-                        if (iterator.next() == origAppToken) {
-                            break;
-                        }
-                    } 
+                    // return indices to same place.
+                    taskNdx = origTaskNdx;
+                    tokenNdx = origTokenNdx;
                 }
             }