Revert ActivityManager changes for tasks. DO NOT MERGE

Keeping all activity=>task changes in master and removing them
from jb-mr2.

Revert "Update histories simultaneously."
Revert "Add null check to setAppGroupId."
Revert "Fix crashing bug in validator."
Revert "Switch topRunning* and moveTaskTo*"
Revert "Begin switch over to task based history."
Revert "Reset and reuse Iterators and don't new() one."
Revert "Remove AppWindowToken lists."
Revert "Fix build."
Revert "Remove unused App methods."
Revert "Stop using AppToken movement and start using Task."
Revert "Replace access to mAppTokens with AppTokenIterator"
Revert "Refactor setAppOpVisibility implementation."
Revert "Add AppWindowTokens to TaskList."
Revert "Make ActivityStack.mHistory private."
Revert "Migrate AppWindowToken lists into DisplayContent."

Change-Id: I5722c9a4956dccb52864207e2967690bc58e4ebb
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 22af3d5..f226683 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -37,7 +37,6 @@
 
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
@@ -197,7 +196,7 @@
     static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
     static final boolean DEBUG_MU = localLOGV || false;
     static final boolean DEBUG_IMMERSIVE = localLOGV || false;
-    static final boolean VALIDATE_TOKENS = true;
+    static final boolean VALIDATE_TOKENS = false;
     static final boolean SHOW_ACTIVITY_START_TIME = true;
     
     // Control over CPU and battery monitoring.
@@ -329,7 +328,7 @@
     /**
      * List of intents that were used to start the most recent tasks.
      */
-    private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
+    final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
 
     public class PendingActivityExtras extends Binder implements Runnable {
         public final ActivityRecord activity;
@@ -597,8 +596,13 @@
      * List of PendingThumbnailsRecord objects of clients who are still
      * waiting to receive all of the thumbnails for a task.
      */
-    final ArrayList<PendingThumbnailsRecord> mPendingThumbnails =
-            new ArrayList<PendingThumbnailsRecord>();
+    final ArrayList mPendingThumbnails = new ArrayList();
+
+    /**
+     * List of HistoryRecord objects that have been finished and must
+     * still report back to a pending thumbnail receiver.
+     */
+    final ArrayList mCancelledThumbnails = new ArrayList();
 
     final ProviderMap mProviderMap;
 
@@ -2838,8 +2842,11 @@
             for (int i=0; i<activities.size(); i++) {
                 ActivityRecord r = activities.get(i);
                 if (!r.finishing) {
-                    mMainStack.finishActivityLocked(r, Activity.RESULT_CANCELED,
-                            null, "finish-heavy", true);
+                    int index = mMainStack.indexOfTokenLocked(r.appToken);
+                    if (index >= 0) {
+                        mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
+                                null, "finish-heavy", true);
+                    }
                 }
             }
             
@@ -2925,13 +2932,22 @@
         }
     }
 
-    @Override
     public boolean willActivityBeVisible(IBinder token) {
         synchronized(this) {
-            return mMainStack.willActivityBeVisibleLocked(token);
+            int i;
+            for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
+                ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+                if (r.appToken == token) {
+                    return true;
+                }
+                if (r.fullscreen && !r.finishing) {
+                    return false;
+                }
+            }
+            return true;
         }
     }
-
+    
     public void overridePendingTransition(IBinder token, String packageName,
             int enterAnim, int exitAnim) {
         synchronized(this) {
@@ -3701,7 +3717,13 @@
         }
         mWindowManager.closeSystemDialogs(reason);
 
-        mMainStack.closeSystemDialogsLocked();
+        for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
+            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+            if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
+                r.stack.finishActivityLocked(r, i,
+                        Activity.RESULT_CANCELED, null, "close-sys", true);
+            }
+        }
 
         broadcastIntentLocked(null, null, intent, null,
                 null, 0, null, null, null, AppOpsManager.OP_NONE, false, false, -1,
@@ -3908,12 +3930,37 @@
         boolean didSomething = killPackageProcessesLocked(name, appId, userId,
                 -100, callerWillRestart, true, doit, evenPersistent,
                 name == null ? ("force stop user " + userId) : ("force stop " + name));
-
-        if (mMainStack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
-            if (!doit) {
-                return true;
+        
+        TaskRecord lastTask = null;
+        for (i=0; i<mMainStack.mHistory.size(); i++) {
+            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+            final boolean samePackage = r.packageName.equals(name)
+                    || (name == null && r.userId == userId);
+            if ((userId == UserHandle.USER_ALL || r.userId == userId)
+                    && (samePackage || r.task == lastTask)
+                    && (r.app == null || evenPersistent || !r.app.persistent)) {
+                if (!doit) {
+                    if (r.finishing) {
+                        // If this activity is just finishing, then it is not
+                        // interesting as far as something to stop.
+                        continue;
+                    }
+                    return true;
+                }
+                didSomething = true;
+                Slog.i(TAG, "  Force finishing activity " + r);
+                if (samePackage) {
+                    if (r.app != null) {
+                        r.app.removed = true;
+                    }
+                    r.app = null;
+                }
+                lastTask = r.task;
+                if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+                        null, "force-stop", true)) {
+                    i--;
+                }
             }
-            didSomething = true;
         }
 
         if (mServices.forceStopLocked(name, userId, evenPersistent, doit)) {
@@ -5623,12 +5670,12 @@
     // TASK MANAGEMENT
     // =========================================================
 
-    @Override
-    public List<RunningTaskInfo> getTasks(int maxNum, int flags,
+    public List getTasks(int maxNum, int flags,
                          IThumbnailReceiver receiver) {
-        ArrayList<RunningTaskInfo> list = new ArrayList<RunningTaskInfo>();
+        ArrayList list = new ArrayList();
 
-        PendingThumbnailsRecord pending = new PendingThumbnailsRecord(receiver);
+        PendingThumbnailsRecord pending = null;
+        IApplicationThread topThumbnail = null;
         ActivityRecord topRecord = null;
 
         synchronized(this) {
@@ -5654,19 +5701,88 @@
                 throw new SecurityException(msg);
             }
 
-            topRecord = mMainStack.getTasksLocked(maxNum, receiver, pending, list);
+            int pos = mMainStack.mHistory.size()-1;
+            ActivityRecord next =
+                pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
+            ActivityRecord top = null;
+            TaskRecord curTask = null;
+            int numActivities = 0;
+            int numRunning = 0;
+            while (pos >= 0 && maxNum > 0) {
+                final ActivityRecord r = next;
+                pos--;
+                next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
 
-            if (!pending.pendingRecords.isEmpty()) {
+                // Initialize state for next task if needed.
+                if (top == null ||
+                        (top.state == ActivityState.INITIALIZING
+                            && top.task == r.task)) {
+                    top = r;
+                    curTask = r.task;
+                    numActivities = numRunning = 0;
+                }
+
+                // Add 'r' into the current task.
+                numActivities++;
+                if (r.app != null && r.app.thread != null) {
+                    numRunning++;
+                }
+
+                if (localLOGV) Slog.v(
+                    TAG, r.intent.getComponent().flattenToShortString()
+                    + ": task=" + r.task);
+
+                // If the next one is a different task, generate a new
+                // TaskInfo entry for what we have.
+                if (next == null || next.task != curTask) {
+                    ActivityManager.RunningTaskInfo ci
+                            = new ActivityManager.RunningTaskInfo();
+                    ci.id = curTask.taskId;
+                    ci.baseActivity = r.intent.getComponent();
+                    ci.topActivity = top.intent.getComponent();
+                    if (top.thumbHolder != null) {
+                        ci.description = top.thumbHolder.lastDescription;
+                    }
+                    ci.numActivities = numActivities;
+                    ci.numRunning = numRunning;
+                    //System.out.println(
+                    //    "#" + maxNum + ": " + " descr=" + ci.description);
+                    if (ci.thumbnail == null && receiver != null) {
+                        if (localLOGV) Slog.v(
+                            TAG, "State=" + top.state + "Idle=" + top.idle
+                            + " app=" + top.app
+                            + " thr=" + (top.app != null ? top.app.thread : null));
+                        if (top.state == ActivityState.RESUMED
+                                || top.state == ActivityState.PAUSING) {
+                            if (top.idle && top.app != null
+                                && top.app.thread != null) {
+                                topRecord = top;
+                                topThumbnail = top.app.thread;
+                            } else {
+                                top.thumbnailNeeded = true;
+                            }
+                        }
+                        if (pending == null) {
+                            pending = new PendingThumbnailsRecord(receiver);
+                        }
+                        pending.pendingRecords.add(top);
+                    }
+                    list.add(ci);
+                    maxNum--;
+                    top = null;
+                }
+            }
+
+            if (pending != null) {
                 mPendingThumbnails.add(pending);
             }
         }
 
         if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
 
-        if (topRecord != null) {
+        if (topThumbnail != null) {
             if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
             try {
-                IApplicationThread topThumbnail = topRecord.app.thread;
                 topThumbnail.requestThumbnail(topRecord.appToken);
             } catch (Exception e) {
                 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
@@ -5901,6 +6017,43 @@
         return false;
     }
     
+    private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
+        int j;
+        TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task; 
+        TaskRecord jt = startTask;
+        
+        // First look backwards
+        for (j=startIndex-1; j>=0; j--) {
+            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
+            if (r.task != jt) {
+                jt = r.task;
+                if (affinity.equals(jt.affinity)) {
+                    return j;
+                }
+            }
+        }
+        
+        // Now look forwards
+        final int N = mMainStack.mHistory.size();
+        jt = startTask;
+        for (j=startIndex+1; j<N; j++) {
+            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
+            if (r.task != jt) {
+                if (affinity.equals(jt.affinity)) {
+                    return j;
+                }
+                jt = r.task;
+            }
+        }
+        
+        // Might it be at the top?
+        if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
+            return N-1;
+        }
+        
+        return -1;
+    }
+    
     /**
      * TODO: Add mController hook
      */
@@ -5929,8 +6082,20 @@
                     mMainStack.moveTaskToFrontLocked(tr, null, options);
                     return;
                 }
-                if (mMainStack.findTaskToMoveToFrontLocked(task, flags, options)) {
-                    return;
+                for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
+                    ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
+                    if (hr.task.taskId == task) {
+                        if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
+                            mMainStack.mUserLeaving = true;
+                        }
+                        if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
+                            // Caller wants the home activity moved with it.  To accomplish this,
+                            // we'll just move the home task to the top first.
+                            mMainStack.moveHomeToFrontLocked();
+                        }
+                        mMainStack.moveTaskToFrontLocked(hr.task, null, options);
+                        return;
+                    }
                 }
             } finally {
                 Binder.restoreCallingIdentity(origId);
@@ -5970,7 +6135,7 @@
         enforceNotIsolatedCaller("moveActivityTaskToBack");
         synchronized(this) {
             final long origId = Binder.clearCallingIdentity();
-            int taskId = mMainStack.getTaskForActivityLocked(token, !nonRoot);
+            int taskId = getTaskForActivityLocked(token, !nonRoot);
             if (taskId >= 0) {
                 return mMainStack.moveTaskToBackLocked(taskId, null);
             }
@@ -6000,10 +6165,27 @@
 
     public int getTaskForActivity(IBinder token, boolean onlyRoot) {
         synchronized(this) {
-            return mMainStack.getTaskForActivityLocked(token, onlyRoot);
+            return getTaskForActivityLocked(token, onlyRoot);
         }
     }
 
+    int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
+        final int N = mMainStack.mHistory.size();
+        TaskRecord lastTask = null;
+        for (int i=0; i<N; i++) {
+            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+            if (r.appToken == token) {
+                if (!onlyRoot || lastTask != r.task) {
+                    return r.task.taskId;
+                }
+                return -1;
+            }
+            lastTask = r.task;
+        }
+
+        return -1;
+    }
+
     // =========================================================
     // THUMBNAILS
     // =========================================================
@@ -6909,10 +7091,13 @@
                 "unhandledBack()");
 
         synchronized(this) {
-            final long origId = Binder.clearCallingIdentity();
-            try {
-                mMainStack.unhandledBackLocked();
-            } finally {
+            int count = mMainStack.mHistory.size();
+            if (DEBUG_SWITCH) Slog.d(
+                TAG, "Performing unhandledBack(): stack size = " + count);
+            if (count > 1) {
+                final long origId = Binder.clearCallingIdentity();
+                mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
+                        count-1, Activity.RESULT_CANCELED, null, "unhandled-back", true);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -7974,7 +8159,15 @@
                     + " has crashed too many times: killing!");
             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
                     app.userId, app.info.processName, app.uid);
-            mMainStack.handleAppCrashLocked(app);
+            for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
+                ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+                if (r.app == app) {
+                    Slog.w(TAG, "  Force finishing activity "
+                        + r.intent.getComponent().flattenToShortString());
+                    r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+                            null, "crashed", false);
+                }
+            }
             if (!app.persistent) {
                 // We don't want to start this process again until the user
                 // explicitly does so...  but for persistent process, we really
@@ -7999,7 +8192,33 @@
             }
             mMainStack.resumeTopActivityLocked(null);
         } else {
-            mMainStack.finishTopRunningActivityLocked(app);
+            ActivityRecord r = mMainStack.topRunningActivityLocked(null);
+            if (r != null && r.app == app) {
+                // If the top running activity is from this crashing
+                // process, then terminate it to avoid getting in a loop.
+                Slog.w(TAG, "  Force finishing activity "
+                        + r.intent.getComponent().flattenToShortString());
+                int index = mMainStack.indexOfActivityLocked(r);
+                r.stack.finishActivityLocked(r, index,
+                        Activity.RESULT_CANCELED, null, "crashed", false);
+                // Also terminate any activities below it that aren't yet
+                // stopped, to avoid a situation where one will get
+                // re-start our crashing activity once it gets resumed again.
+                index--;
+                if (index >= 0) {
+                    r = (ActivityRecord)mMainStack.mHistory.get(index);
+                    if (r.state == ActivityState.RESUMED
+                            || r.state == ActivityState.PAUSING
+                            || r.state == ActivityState.PAUSED) {
+                        if (!r.isHomeActivity || mHomeProcess != r.app) {
+                            Slog.w(TAG, "  Force finishing activity "
+                                    + r.intent.getComponent().flattenToShortString());
+                            r.stack.finishActivityLocked(r, index,
+                                    Activity.RESULT_CANCELED, null, "crashed", false);
+                        }
+                    }
+                }
+            }
         }
 
         // Bump up the crash count of any services currently running in the proc.
@@ -9018,7 +9237,8 @@
             int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
         pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
         pw.println("  Main stack:");
-        mMainStack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
+        dumpHistoryList(fd, pw, mMainStack.mHistory, "  ", "Hist", true, !dumpAll, dumpClient,
+                dumpPackage);
         pw.println(" ");
         pw.println("  Running activities (most recent first):");
         dumpHistoryList(fd, pw, mMainStack.mLRUActivities, "  ", "Run", false, !dumpAll, false,
@@ -9548,10 +9768,32 @@
      */
     protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
             int opti, boolean dumpAll) {
-        ArrayList<ActivityRecord> activities;
-        
-        synchronized (this) {
-            activities = mMainStack.getDumpActivitiesLocked(name);
+        ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
+
+        if ("all".equals(name)) {
+            synchronized (this) {
+                for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+                    activities.add(r1);
+                }
+            }
+        } else if ("top".equals(name)) {
+            synchronized (this) {
+                final int N = mMainStack.mHistory.size();
+                if (N > 0) {
+                    activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
+                }
+            }
+        } else {
+            ItemMatcher matcher = new ItemMatcher();
+            matcher.build(name);
+
+            synchronized (this) {
+                for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+                    if (matcher.match(r1, r1.intent.getComponent())) {
+                        activities.add(r1);
+                    }
+                }
+            }
         }
 
         if (activities.size() <= 0) {
@@ -9803,7 +10045,7 @@
         return needSep;
     }
 
-    static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
+    private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
             String prefix, String label, boolean complete, boolean brief, boolean client,
             String dumpPackage) {
         TaskRecord lastTask = null;
@@ -12341,14 +12583,95 @@
 
     public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
             Intent resultData) {
+        ComponentName dest = destIntent.getComponent();
 
         synchronized (this) {
             ActivityRecord srec = ActivityRecord.forToken(token);
             if (srec == null) {
                 return false;
             }
-            ActivityStack stack = srec.stack;
-            return stack.navigateUpToLocked(srec, destIntent, resultCode, resultData);
+            ArrayList<ActivityRecord> history = srec.stack.mHistory;
+            final int start = history.indexOf(srec);
+            if (start < 0) {
+                // Current activity is not in history stack; do nothing.
+                return false;
+            }
+            int finishTo = start - 1;
+            ActivityRecord parent = null;
+            boolean foundParentInTask = false;
+            if (dest != null) {
+                TaskRecord tr = srec.task;
+                for (int i = start - 1; i >= 0; i--) {
+                    ActivityRecord r = history.get(i);
+                    if (tr != r.task) {
+                        // Couldn't find parent in the same task; stop at the one above this.
+                        // (Root of current task; in-app "home" behavior)
+                        // Always at least finish the current activity.
+                        finishTo = Math.min(start - 1, i + 1);
+                        parent = history.get(finishTo);
+                        break;
+                    } else if (r.info.packageName.equals(dest.getPackageName()) &&
+                            r.info.name.equals(dest.getClassName())) {
+                        finishTo = i;
+                        parent = r;
+                        foundParentInTask = true;
+                        break;
+                    }
+                }
+            }
+
+            if (mController != null) {
+                ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
+                if (next != null) {
+                    // ask watcher if this is allowed
+                    boolean resumeOK = true;
+                    try {
+                        resumeOK = mController.activityResuming(next.packageName);
+                    } catch (RemoteException e) {
+                        mController = null;
+                    }
+
+                    if (!resumeOK) {
+                        return false;
+                    }
+                }
+            }
+            final long origId = Binder.clearCallingIdentity();
+            for (int i = start; i > finishTo; i--) {
+                ActivityRecord r = history.get(i);
+                mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData,
+                        "navigate-up", true);
+                // Only return the supplied result for the first activity finished
+                resultCode = Activity.RESULT_CANCELED;
+                resultData = null;
+            }
+
+            if (parent != null && foundParentInTask) {
+                final int parentLaunchMode = parent.info.launchMode;
+                final int destIntentFlags = destIntent.getFlags();
+                if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
+                        parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
+                        parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
+                        (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
+                    parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
+                } else {
+                    try {
+                        ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
+                                destIntent.getComponent(), 0, srec.userId);
+                        int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
+                                null, aInfo, parent.appToken, null,
+                                0, -1, parent.launchedFromUid, parent.launchedFromPackage,
+                                0, null, true, null);
+                        foundParentInTask = res == ActivityManager.START_SUCCESS;
+                    } catch (RemoteException e) {
+                        foundParentInTask = false;
+                    }
+                    mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
+                            resultData, "navigate-up", true);
+                }
+            }
+            Binder.restoreCallingIdentity(origId);
+            return foundParentInTask;
         }
     }
 
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index a2f3372..cde17c9 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -22,7 +22,6 @@
 
 import android.app.Activity;
 import android.app.ActivityOptions;
-import android.app.ResultInfo;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -96,9 +95,9 @@
     ActivityRecord resultTo; // who started this entry, so will get our reply
     final String resultWho; // additional identifier for use by resultTo.
     final int requestCode;  // code given by requester (resultTo)
-    ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
+    ArrayList results;      // pending ActivityResult objs we have received
     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
-    ArrayList<Intent> newIntents; // any pending new intents for single-top mode
+    ArrayList newIntents;   // any pending new intents for single-top mode
     ActivityOptions pendingOptions; // most recently given options
     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
     UriPermissionOwner uriPermissions; // current special URI access perms.
@@ -471,8 +470,6 @@
     void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
         if (inHistory && !finishing) {
             if (task != null) {
-                // TODO: If this is the last ActivityRecord in task, remove from ActivityStack.
-                task.removeActivity(this);
                 task.numActivities--;
             }
             if (newTask != null) {
@@ -507,7 +504,6 @@
             inHistory = false;
             if (task != null && !finishing) {
                 task.numActivities--;
-                task = null;
             }
             clearOptionsLocked();
         }
@@ -542,7 +538,7 @@
         ActivityResult r = new ActivityResult(from, resultWho,
         		requestCode, resultCode, resultData);
         if (results == null) {
-            results = new ArrayList<ResultInfo>();
+            results = new ArrayList();
         }
         results.add(r);
     }
@@ -953,8 +949,6 @@
         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(' ');
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index e0b8015..526b24f 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -21,23 +21,18 @@
 
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.am.ActivityManagerService.ItemMatcher;
 import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
 import com.android.server.wm.AppTransition;
-import com.android.server.wm.TaskGroup;
 
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
-import android.app.IActivityController;
 import android.app.IActivityManager;
-import android.app.IThumbnailReceiver;
 import android.app.IThumbnailRetriever;
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
 import android.app.ResultInfo;
-import android.app.ActivityManager.RunningTaskInfo;
 import android.app.IActivityManager.WaitResult;
 import android.content.ComponentName;
 import android.content.Context;
@@ -54,7 +49,6 @@
 import android.graphics.Bitmap.Config;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -67,12 +61,9 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.view.Display;
 
-import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -100,8 +91,7 @@
     static final boolean DEBUG_APP = false;
 
     static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
-    static final boolean VALIDATE_TASK_REPLACE = true;
-
+    
     // How long we wait until giving up on the last activity telling us it
     // is idle.
     static final int IDLE_TIMEOUT = 10*1000;
@@ -140,7 +130,7 @@
     // Set to false to disable the preview that is shown while a new activity
     // is being started.
     static final boolean SHOW_APP_STARTING_PREVIEW = true;
-
+    
     enum ActivityState {
         INITIALIZING,
         RESUMED,
@@ -157,28 +147,17 @@
     final boolean mMainStack;
     
     final Context mContext;
-
+    
     /**
      * The back history of all previous (and possibly still
-     * running) activities.  It contains #ActivityRecord objects.
+     * running) activities.  It contains HistoryRecord objects.
      */
-    private final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
-
-    /**
-     * The back history of all previous (and possibly still
-     * running) activities.  It contains #TaskRecord objects.
-     */
-    private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
-
-    /**
-     * Mapping from taskId to TaskRecord
-     */
-    private SparseArray<TaskRecord> mTaskIdToTaskRecord = new SparseArray<TaskRecord>();
+    final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
 
     /**
      * Used for validating app tokens with window manager.
      */
-    final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
+    final ArrayList<IBinder> mValidateAppTokens = new ArrayList<IBinder>();
 
     /**
      * List of running activities, sorted by recent usage.
@@ -310,12 +289,6 @@
     private ActivityRecord mLastScreenshotActivity = null;
     private Bitmap mLastScreenshotBitmap = null;
 
-    /**
-     * List of ActivityRecord objects that have been finished and must
-     * still report back to a pending thumbnail receiver.
-     */
-    private final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
-
     int mThumbnailWidth = -1;
     int mThumbnailHeight = -1;
 
@@ -345,8 +318,6 @@
 
     final Handler mHandler;
 
-    String mLastHistoryModifier;
-
     final class ActivityStackHandler extends Handler {
         //public Handler() {
         //    if (localLOGV) Slog.v(TAG, "Handler started!");
@@ -473,66 +444,26 @@
     }
 
     final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
-        ActivityRecord newAr = newTopRunningActivityLocked(notTop);
-
         int i = mHistory.size()-1;
         while (i >= 0) {
             ActivityRecord r = mHistory.get(i);
             if (!r.finishing && r != notTop && okToShow(r)) {
-                if (VALIDATE_TASK_REPLACE && newAr != r) logHistories(
-                        "topRunningActivityLocked", true);
                 return r;
             }
             i--;
         }
-        if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
-                "topRunningActivityLocked: mismatch: newAr!=null");
-        return null;
-    }
-
-    final ActivityRecord newTopRunningActivityLocked(ActivityRecord notTop) {
-        for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
-            final TaskRecord task = mTaskHistory.get(i);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int j = activities.size() - 1; j >= 0; --j) {
-                ActivityRecord r = activities.get(j);
-                if (!r.finishing && r != notTop && okToShow(r)) {
-                    return r;
-                }
-            }
-        }
         return null;
     }
 
     final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
-        ActivityRecord newAr = newTopRunningNonDelayedActivityLocked(notTop);
-
         int i = mHistory.size()-1;
         while (i >= 0) {
             ActivityRecord r = mHistory.get(i);
             if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
-                if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
-                    "topRunningNonDelayedActivityLocked: mismatch: newAr=" + newAr + " r=" + r);
                 return r;
             }
             i--;
         }
-        if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
-                "topRunningNonDelayedActivityLocked: mismatch: newAr!=null");
-        return null;
-    }
-
-    final ActivityRecord newTopRunningNonDelayedActivityLocked(ActivityRecord notTop) {
-        for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
-            final TaskRecord task = mTaskHistory.get(i);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int j = activities.size() - 1; j >= 0; --j) {
-                ActivityRecord r = activities.get(j);
-                if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
-                    return r;
-                }
-            }
-        }
         return null;
     }
 
@@ -546,111 +477,35 @@
      * @return Returns the HistoryRecord of the next activity on the stack.
      */
     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
-        ActivityRecord newAr = newTopRunningActivityLocked(token, taskId);
-
         int i = mHistory.size()-1;
         while (i >= 0) {
             ActivityRecord r = mHistory.get(i);
             // Note: the taskId check depends on real taskId fields being non-zero
             if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)
                     && okToShow(r)) {
-                if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
-                        "topRunningActivityLocked(token): mismatch: newAr=" + newAr + " r=" + r);
                 return r;
             }
             i--;
         }
-        if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
-                "topRunningActivityLocked(token): mismatch: newAr!=null");
         return null;
     }
 
-    final ActivityRecord newTopRunningActivityLocked(IBinder token, int taskId) {
-        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            TaskRecord task = mTaskHistory.get(taskNdx);
-            if (task.taskId == taskId) {
-                continue;
-            }
-            ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int i = activities.size() - 1; i >= 0; --i) {
-                final ActivityRecord r = activities.get(i);
-                // Note: the taskId check depends on real taskId fields being non-zero
-                if (!r.finishing && (token != r.appToken) && okToShow(r)) {
-                    return r;
-                }
-            }
-        }
-        return null;
-    }
-
-    private final int indexOfTokenLocked(IBinder token) {
+    final int indexOfTokenLocked(IBinder token) {
         return mHistory.indexOf(ActivityRecord.forToken(token));
     }
 
-    final ActivityRecord isInStackLocked(IBinder token) {
-        ActivityRecord newAr = newIsInStackLocked(token);
+    final int indexOfActivityLocked(ActivityRecord r) {
+        return mHistory.indexOf(r);
+    }
 
+    final ActivityRecord isInStackLocked(IBinder token) {
         ActivityRecord r = ActivityRecord.forToken(token);
         if (mHistory.contains(r)) {
-            if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
-                    "isInStackLocked: mismatch: newAr=" + newAr + " r=" + r);
             return r;
         }
-        if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
-                "isInStackLocked: mismatch: newAr!=null");
         return null;
     }
 
-    final ActivityRecord newIsInStackLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.forToken(token);
-        if (r != null) {
-            final TaskRecord task = r.task;
-            if (mTaskHistory.contains(task) && task.mActivities.contains(r)) {
-                return r;
-            }
-        }
-        return null;
-    }
-
-    int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
-        int newTaskId = newGetTaskForActivityLocked(token, onlyRoot);
-
-        TaskRecord lastTask = null;
-        final int N = mHistory.size();
-        for (int i = 0; i < N; i++) {
-            ActivityRecord r = mHistory.get(i);
-            if (r.appToken == token) {
-                if (!onlyRoot || lastTask != r.task) {
-                    if (VALIDATE_TASK_REPLACE && newTaskId != r.task.taskId) Slog.w(TAG,
-                            "getTaskForActivityLocked: mismatch: new=" + newTaskId
-                            + " taskId=" + r.task.taskId);
-                    return r.task.taskId;
-                }
-                if (VALIDATE_TASK_REPLACE && newTaskId != -1) Slog.w(TAG,
-                    "getTaskForActivityLocked: mismatch: newTaskId=" + newTaskId + " not -1.");
-                return -1;
-            }
-            lastTask = r.task;
-        }
-
-        if (VALIDATE_TASK_REPLACE && newTaskId != -1) Slog.w(TAG,
-            "getTaskForActivityLocked: mismatch at end: newTaskId=" + newTaskId + " not -1.");
-        return -1;
-    }
-
-    int newGetTaskForActivityLocked(IBinder token, boolean onlyRoot) {
-        final ActivityRecord r = ActivityRecord.forToken(token);
-        if (r == null) {
-            return -1;
-        }
-        final TaskRecord task = r.task;
-        switch (task.mActivities.indexOf(r)) {
-            case -1: return -1;
-            case 0: return task.taskId;
-            default: return onlyRoot ? -1 : task.taskId;
-        }
-    }
-
     private final boolean updateLRUListLocked(ActivityRecord r) {
         final boolean hadit = mLRUActivities.remove(r);
         mLRUActivities.add(r);
@@ -743,29 +598,17 @@
      * @return whether there are any activities for the specified user.
      */
     final boolean switchUserLocked(int userId, UserStartedState uss) {
-        if (VALIDATE_TOKENS) {
-            validateAppTokensLocked();
-        }
-        final boolean newResult = newSwitchUserLocked(userId, uss);
-
         mCurrentUser = userId;
         mStartingUsers.add(uss);
 
         // Only one activity? Nothing to do...
-        if (mHistory.size() < 2) {
-            if (VALIDATE_TASK_REPLACE && newResult) Slog.w(TAG,
-                    "switchUserLocked: mismatch: " + newResult + " " + false);
+        if (mHistory.size() < 2)
             return false;
-        }
 
         boolean haveActivities = false;
         // Check if the top activity is from the new user.
         ActivityRecord top = mHistory.get(mHistory.size() - 1);
-        if (top.userId == userId) {
-            if (VALIDATE_TASK_REPLACE && !newResult) Slog.w(TAG,
-                    "switchUserLocked: mismatch: " + newResult + " " + true);
-            return true;
-        }
+        if (top.userId == userId) return true;
         // Otherwise, move the user's activities to the top.
         int N = mHistory.size();
         int i = 0;
@@ -782,44 +625,7 @@
             }
         }
         // Transition from the old top to the new top
-        if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
-                "switchUserLocked: calling resumeTopActivity " + top);
         resumeTopActivityLocked(top);
-        if (VALIDATE_TASK_REPLACE && (newResult != haveActivities)) Slog.w(TAG,
-                    "switchUserLocked: mismatch: " + newResult + " " + haveActivities);
-        return haveActivities;
-    }
-
-    /*
-     * Move the activities around in the stack to bring a user to the foreground.
-     * @return whether there are any activities for the specified user.
-     */
-    final boolean newSwitchUserLocked(int userId, UserStartedState uss) {
-//        mStartingUsers.add(uss);
-        if (mCurrentUser == userId) {
-            return true;
-        }
-        mCurrentUser = userId;
-
-        // Move userId's tasks to the top.
-        boolean haveActivities = false;
-        TaskRecord task = null;
-        int index = mTaskHistory.size();
-        for (int i = 0; i < index; ++i) {
-            task = mTaskHistory.get(i);
-            if (task.userId == userId) {
-                haveActivities = true;
-                mTaskHistory.remove(i);
-                mTaskHistory.add(task);
-                --index;
-            }
-        }
-
-        // task is now the original topmost TaskRecord. Transition from the old top to the new top.
-        ActivityRecord top = task != null ? task.getTopActivity() : null;
-        if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
-                "newSwitchUserLocked: would call resumeTopActivity " + top);
-//        resumeTopActivityLocked(top);
         return haveActivities;
     }
 
@@ -903,13 +709,7 @@
                 try {
                     profileFd = profileFd.dup();
                 } catch (IOException e) {
-                    if (profileFd != null) {
-                        try {
-                            profileFd.close();
-                        } catch (IOException o) {
-                        }
-                        profileFd = null;
-                    }
+                    profileFd = null;
                 }
             }
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
@@ -1057,9 +857,6 @@
             mGoingToSleep.release();
         }
         // Ensure activities are no longer sleeping.
-        if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords(true);
-        }
         for (int i=mHistory.size()-1; i>=0; i--) {
             ActivityRecord r = mHistory.get(i);
             r.setSleeping(false);
@@ -1104,9 +901,6 @@
 
             // Make sure any stopped but visible activities are now sleeping.
             // This ensures that the activity's onStop() is called.
-            if (VALIDATE_TASK_REPLACE) {
-                verifyActivityRecords(true);
-            }
             for (int i=mHistory.size()-1; i>=0; i--) {
                 ActivityRecord r = mHistory.get(i);
                 if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
@@ -1251,9 +1045,6 @@
         ActivityRecord r = null;
 
         synchronized (mService) {
-            if (VALIDATE_TASK_REPLACE) {
-                verifyActivityRecords(true);
-            }
             int index = indexOfTokenLocked(token);
             if (index >= 0) {
                 r = mHistory.get(index);
@@ -1271,9 +1062,6 @@
         ActivityRecord r = null;
 
         synchronized (mService) {
-            if (VALIDATE_TASK_REPLACE) {
-                verifyActivityRecords(true);
-            }
             int index = indexOfTokenLocked(token);
             if (index >= 0) {
                 r = mHistory.get(index);
@@ -1486,9 +1274,6 @@
 
         // If the top activity is not fullscreen, then we need to
         // make sure any activities under it are now visible.
-        if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords(true);
-        }
         final int count = mHistory.size();
         int i = count-1;
         while (mHistory.get(i) != top) {
@@ -1937,7 +1722,7 @@
             
             try {
                 // Deliver all pending results.
-                ArrayList<ResultInfo> a = next.results;
+                ArrayList a = next.results;
                 if (a != null) {
                     final int N = a.size();
                     if (!next.finishing && N > 0) {
@@ -2025,21 +1810,8 @@
         return true;
     }
 
-    /** Temporary until startActivityLocked is rewritten for tasks. */
-    private int convertAddPos(int addPos) {
-        final int taskId = mHistory.get(addPos).task.taskId;
-        addPos--;
-        int taskOffset = 0;
-        while (addPos >= 0 && taskId == mHistory.get(addPos).task.taskId) {
-            ++taskOffset;
-            --addPos;
-        }
-        return taskOffset;
-    }
-
     private final void startActivityLocked(ActivityRecord r, boolean newTask,
             boolean doResume, boolean keepCurTransition, Bundle options) {
-        mLastHistoryModifier = "startActivityLocked";
         final int NH = mHistory.size();
 
         int addPos = -1;
@@ -2064,15 +1836,13 @@
                             Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
                                     here);
                         }
-                        r.task.addActivityToTop(r);
                         mHistory.add(addPos, r);
                         r.putInHistory();
-                        mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken,
-                                r.task.taskId, r.info.screenOrientation, r.fullscreen,
+                        mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
+                                r.info.screenOrientation, r.fullscreen,
                                 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
                         if (VALIDATE_TOKENS) {
                             validateAppTokensLocked();
-                            verifyActivityRecords(true);
                         }
                         ActivityOptions.abort(options);
                         return;
@@ -2105,15 +1875,9 @@
             here.fillInStackTrace();
             Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
         }
-        r.task.addActivityToTop(r);
         mHistory.add(addPos, r);
         r.putInHistory();
         r.frontOfTask = newTask;
-        if (VALIDATE_TASK_REPLACE) {
-            if (verifyActivityRecords(false)) {
-                Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
-            }
-        }
         if (NH > 0) {
             // We want to show the starting preview window if we are
             // switching to a new task, or the next activity's process is
@@ -2139,8 +1903,8 @@
                 mNoAnimActivities.remove(r);
             }
             r.updateOptionsLocked(options);
-            mService.mWindowManager.addAppToken(convertAddPos(addPos),
-                    r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
+            mService.mWindowManager.addAppToken(
+                    addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
             boolean doShow = true;
             if (newTask) {
@@ -2178,7 +1942,7 @@
         } else {
             // If this is the first activity, don't do any fancy animations,
             // because there is nothing for it to animate on top of.
-            mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken, r.task.taskId,
+            mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
                     r.info.screenOrientation, r.fullscreen,
                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
             ActivityOptions.abort(options);
@@ -2190,27 +1954,13 @@
         if (doResume) {
             resumeTopActivityLocked(null);
         }
-        if (VALIDATE_TASK_REPLACE) {
-            if (verifyActivityRecords(true)) {
-                Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
-            }
-        }
     }
 
     final void validateAppTokensLocked() {
         mValidateAppTokens.clear();
         mValidateAppTokens.ensureCapacity(mHistory.size());
-        int taskId = Integer.MIN_VALUE;
-        TaskGroup task = null;
         for (int i=0; i<mHistory.size(); i++) {
-            final ActivityRecord r = mHistory.get(i);
-            if (taskId != r.task.taskId) {
-                taskId = r.task.taskId;
-                task = new TaskGroup();
-                task.taskId = taskId;
-                mValidateAppTokens.add(task);
-            }
-            task.tokens.add(r.appToken);
+            mValidateAppTokens.add(mHistory.get(i).appToken);
         }
         mService.mWindowManager.validateAppTokens(mValidateAppTokens);
     }
@@ -2221,8 +1971,6 @@
      */
     private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
             ActivityRecord newActivity) {
-        mLastHistoryModifier = "resetTaskIfNeededLocked";
-
         boolean forceReset = (newActivity.info.flags
                 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
         if (ACTIVITY_INACTIVE_RESET_TIME > 0
@@ -2318,20 +2066,19 @@
                             if (mService.mCurTask <= 0) {
                                 mService.mCurTask = 1;
                             }
-                            target.setTask(createTaskRecord(mService.mCurTask, target.info, null,
-                                    false), null, false);
+                            target.setTask(new TaskRecord(mService.mCurTask, target.info, null),
+                                    null, false);
                             target.task.affinityIntent = target.intent;
                             if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
                                     + " out to new task " + target.task);
                         }
-                        mService.mWindowManager.setAppGroupId(target.appToken, target.task.taskId);
+                        mService.mWindowManager.setAppGroupId(target.appToken, task.taskId);
                         if (replyChainEnd < 0) {
                             replyChainEnd = targetI;
                         }
                         int dstPos = 0;
                         ThumbnailHolder curThumbHolder = target.thumbHolder;
                         boolean gotOptions = !canMoveOptions;
-                        final int taskId = target.task.taskId;
                         for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
                             p = mHistory.get(srcPos);
                             if (p.finishing) {
@@ -2356,15 +2103,14 @@
                             }
                             mHistory.remove(srcPos);
                             mHistory.add(dstPos, p);
-                            mService.mWindowManager.setAppGroupId(p.appToken, taskId);
+                            mService.mWindowManager.moveAppToken(dstPos, p.appToken);
+                            mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
                             dstPos++;
+                            if (VALIDATE_TOKENS) {
+                                validateAppTokensLocked();
+                            }
                             i++;
                         }
-                        rebuildTaskHistory();
-                        mService.mWindowManager.moveTaskToBottom(taskId);
-                        if (VALIDATE_TOKENS) {
-                            validateAppTokensLocked();
-                        }
                         if (taskTop == p) {
                             taskTop = below;
                         }
@@ -2384,7 +2130,8 @@
                             // like these are all in the reply chain.
                             replyChainEnd = targetI+1;
                             while (replyChainEnd < mHistory.size() &&
-                                    (mHistory.get(replyChainEnd)).task == task) {
+                                    (mHistory.get(
+                                                replyChainEnd)).task == task) {
                                 replyChainEnd++;
                             }
                             replyChainEnd--;
@@ -2481,7 +2228,6 @@
                     if (replyChainEnd < 0) {
                         replyChainEnd = targetI;
                     }
-                    final int taskId = task.taskId;
                     if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
                             + targetI + " to " + replyChainEnd);
                     for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
@@ -2507,13 +2253,11 @@
                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
                                 + " from " + srcPos + " to " + lastReparentPos
                                 + " in to resetting task " + task);
-                        mService.mWindowManager.setAppGroupId(p.appToken, taskId);
-                    }
-                    rebuildTaskHistory();
-                    // TODO: This is wrong because it doesn't take lastReparentPos into account.
-                    mService.mWindowManager.moveTaskToTop(taskId);
-                    if (VALIDATE_TOKENS) {
-                        validateAppTokensLocked();
+                        mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
+                        mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
+                        if (VALIDATE_TOKENS) {
+                            validateAppTokensLocked();
+                        }
                     }
                     replyChainEnd = -1;
                     
@@ -2558,9 +2302,6 @@
             }
         }
 
-        if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords(true);
-        }
         return taskTop;
     }
     
@@ -2627,7 +2368,7 @@
                 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
                         && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
                     if (!ret.finishing) {
-                        int index = mHistory.indexOf(ret);
+                        int index = indexOfTokenLocked(ret.appToken);
                         if (index >= 0) {
                             finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
                                     null, "clear", false);
@@ -2725,7 +2466,6 @@
      */
     private final ActivityRecord moveActivityToFrontLocked(int where) {
         ActivityRecord newTop = mHistory.remove(where);
-        newMoveActivityToFrontLocked(newTop);
         int top = mHistory.size();
         ActivityRecord oldTop = mHistory.get(top-1);
         if (DEBUG_ADD_REMOVE) {
@@ -2735,17 +2475,6 @@
                     + top, here);
         }
         mHistory.add(top, newTop);
-        if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords(true);
-        }
-        return newTop;
-    }
-
-    private final ActivityRecord newMoveActivityToFrontLocked(ActivityRecord newTop) {
-        final TaskRecord task = newTop.task;
-        ActivityRecord oldTop = task.getTopActivity();
-        task.mActivities.remove(newTop);
-        task.mActivities.add(newTop);
         oldTop.frontOfTask = false;
         newTop.frontOfTask = true;
         return newTop;
@@ -2756,7 +2485,6 @@
             String resultWho, int requestCode,
             int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
             boolean componentSpecified, ActivityRecord[] outActivity) {
-        mLastHistoryModifier = "startActivityLocked(IApplicationThread)";
 
         int err = ActivityManager.START_SUCCESS;
 
@@ -3239,7 +2967,7 @@
                 if (mService.mCurTask <= 0) {
                     mService.mCurTask = 1;
                 }
-                r.setTask(createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
+                r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
                 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                         + " in new task " + r.task);
             } else {
@@ -3303,7 +3031,7 @@
                 N > 0 ? mHistory.get(N-1) : null;
             r.setTask(prev != null
                     ? prev.task
-                    : createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
+                    : new TaskRecord(mService.mCurTask, r.info, intent), null, true);
             if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                     + " in new guessed " + r.task);
         }
@@ -3795,7 +3523,7 @@
             }
 
             // Get the activity record.
-            int index = mHistory.indexOf(r);
+            int index = indexOfActivityLocked(r);
             if (index >= 0) {
                 res = r;
 
@@ -3851,9 +3579,9 @@
                 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
                 mFinishingActivities.clear();
             }
-            if ((NT=mCancelledThumbnails.size()) > 0) {
-                thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
-                mCancelledThumbnails.clear();
+            if ((NT=mService.mCancelledThumbnails.size()) > 0) {
+                thumbnails = new ArrayList<ActivityRecord>(mService.mCancelledThumbnails);
+                mService.mCancelledThumbnails.clear();
             }
 
             if (mMainStack) {
@@ -3881,7 +3609,7 @@
         // Stop any activities that are scheduled to do so but have been
         // waiting for the next one to start.
         for (i=0; i<NS; i++) {
-            ActivityRecord r = stops.get(i);
+            ActivityRecord r = (ActivityRecord)stops.get(i);
             synchronized (mService) {
                 if (r.finishing) {
                     finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
@@ -3894,7 +3622,7 @@
         // Finish any activities that are scheduled to do so but have been
         // waiting for the next one to start.
         for (i=0; i<NF; i++) {
-            ActivityRecord r = finishes.get(i);
+            ActivityRecord r = (ActivityRecord)finishes.get(i);
             synchronized (mService) {
                 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
             }
@@ -3902,7 +3630,7 @@
 
         // Report back to any thumbnail receivers.
         for (i=0; i<NT; i++) {
-            ActivityRecord r = thumbnails.get(i);
+            ActivityRecord r = (ActivityRecord)thumbnails.get(i);
             mService.sendPendingThumbnail(r, null, null, null, true);
         }
 
@@ -3957,7 +3685,7 @@
 
         int i;
         for (i=mHistory.size()-1; i>=0; i--) {
-            ActivityRecord r = mHistory.get(i);
+            ActivityRecord r = (ActivityRecord)mHistory.get(i);
             if (r.resultTo == self && r.requestCode == requestCode) {
                 if ((r.resultWho == null && resultWho == null) ||
                     (r.resultWho != null && r.resultWho.equals(resultWho))) {
@@ -3969,36 +3697,6 @@
         mService.updateOomAdjLocked();
     }
 
-    final void finishTopRunningActivityLocked(ProcessRecord app) {
-        ActivityRecord r = topRunningActivityLocked(null);
-        if (r != null && r.app == app) {
-            // If the top running activity is from this crashing
-            // process, then terminate it to avoid getting in a loop.
-            Slog.w(TAG, "  Force finishing activity "
-                    + r.intent.getComponent().flattenToShortString());
-            int index = mHistory.indexOf(r);
-            r.stack.finishActivityLocked(r, index,
-                    Activity.RESULT_CANCELED, null, "crashed", false);
-            // Also terminate any activities below it that aren't yet
-            // stopped, to avoid a situation where one will get
-            // re-start our crashing activity once it gets resumed again.
-            index--;
-            if (index >= 0) {
-                r = mHistory.get(index);
-                if (r.state == ActivityState.RESUMED
-                        || r.state == ActivityState.PAUSING
-                        || r.state == ActivityState.PAUSED) {
-                    if (!r.isHomeActivity || mService.mHomeProcess != r.app) {
-                        Slog.w(TAG, "  Force finishing activity "
-                                + r.intent.getComponent().flattenToShortString());
-                        r.stack.finishActivityLocked(r, index,
-                                Activity.RESULT_CANCELED, null, "crashed", false);
-                    }
-                }
-            }
-        }
-    }
-
     final boolean finishActivityAffinityLocked(IBinder token) {
         int index = indexOfTokenLocked(token);
         if (DEBUG_RESULTS) Slog.v(
@@ -4057,19 +3755,6 @@
      * @return Returns true if this activity has been removed from the history
      * list, or false if it is still in the list and will be removed later.
      */
-    final boolean finishActivityLocked(ActivityRecord r,
-            int resultCode, Intent resultData, String reason, boolean oomAdj) {
-        int index = mHistory.indexOf(r);
-        if (index >= 0) {
-            return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
-        }
-        return false;
-    }
-
-    /**
-     * @return Returns true if this activity has been removed from the history
-     * list, or false if it is still in the list and will be removed later.
-     */
     final boolean finishActivityLocked(ActivityRecord r, int index,
             int resultCode, Intent resultData, String reason, boolean oomAdj) {
         return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
@@ -4119,7 +3804,7 @@
             // There are clients waiting to receive thumbnails so, in case
             // this is an activity that someone is waiting for, add it
             // to the pending list so we can correctly update the clients.
-            mCancelledThumbnails.add(r);
+            mService.mCancelledThumbnails.add(r);
         }
 
         if (immediate) {
@@ -4162,7 +3847,7 @@
 
     private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
             int mode, boolean oomAdj) {
-        final int index = mHistory.indexOf(r);
+        final int index = indexOfActivityLocked(r);
         if (index < 0) {
             return null;
         }
@@ -4218,102 +3903,16 @@
                 resumeTopActivityLocked(null);
             }
             return activityRemoved ? null : r;
+        } else {
+            // Need to go through the full pause cycle to get this
+            // activity into the stopped state and then finish it.
+            if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
+            mFinishingActivities.add(r);
+            resumeTopActivityLocked(null);
         }
-
-        // Need to go through the full pause cycle to get this
-        // activity into the stopped state and then finish it.
-        if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
-        mFinishingActivities.add(r);
-        resumeTopActivityLocked(null);
         return r;
     }
 
-    final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
-            Intent resultData) {
-        final int start = mHistory.indexOf(srec);
-        if (start < 0) {
-            // Current activity is not in history stack; do nothing.
-            return false;
-        }
-        int finishTo = start - 1;
-        ActivityRecord parent = null;
-        boolean foundParentInTask = false;
-        ComponentName dest = destIntent.getComponent();
-        if (dest != null) {
-            TaskRecord tr = srec.task;
-            for (int i = start - 1; i >= 0; i--) {
-                ActivityRecord r = mHistory.get(i);
-                if (tr != r.task) {
-                    // Couldn't find parent in the same task; stop at the one above this.
-                    // (Root of current task; in-app "home" behavior)
-                    // Always at least finish the current activity.
-                    finishTo = Math.min(start - 1, i + 1);
-                    parent = mHistory.get(finishTo);
-                    break;
-                } else if (r.info.packageName.equals(dest.getPackageName()) &&
-                        r.info.name.equals(dest.getClassName())) {
-                    finishTo = i;
-                    parent = r;
-                    foundParentInTask = true;
-                    break;
-                }
-            }
-        }
-
-        IActivityController controller = mService.mController;
-        if (controller != null) {
-            ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
-            if (next != null) {
-                // ask watcher if this is allowed
-                boolean resumeOK = true;
-                try {
-                    resumeOK = controller.activityResuming(next.packageName);
-                } catch (RemoteException e) {
-                    mService.mController = null;
-                }
-
-                if (!resumeOK) {
-                    return false;
-                }
-            }
-        }
-        final long origId = Binder.clearCallingIdentity();
-        for (int i = start; i > finishTo; i--) {
-            ActivityRecord r = mHistory.get(i);
-            requestFinishActivityLocked(r.appToken, resultCode, resultData,
-                    "navigate-up", true);
-            // Only return the supplied result for the first activity finished
-            resultCode = Activity.RESULT_CANCELED;
-            resultData = null;
-        }
-
-        if (parent != null && foundParentInTask) {
-            final int parentLaunchMode = parent.info.launchMode;
-            final int destIntentFlags = destIntent.getFlags();
-            if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
-                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
-                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
-                    (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
-                parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
-            } else {
-                try {
-                    ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
-                            destIntent.getComponent(), 0, srec.userId);
-                    int res = startActivityLocked(srec.app.thread, destIntent,
-                            null, aInfo, parent.appToken, null,
-                            0, -1, parent.launchedFromUid, parent.launchedFromPackage,
-                            0, null, true, null);
-                    foundParentInTask = res == ActivityManager.START_SUCCESS;
-                } catch (RemoteException e) {
-                    foundParentInTask = false;
-                }
-                requestFinishActivityLocked(parent.appToken, resultCode,
-                        resultData, "navigate-up", true);
-            }
-        }
-        Binder.restoreCallingIdentity(origId);
-        return foundParentInTask;
-    }
     /**
      * Perform the common clean-up of an activity record.  This is called both
      * as part of destroyActivityLocked() (when destroying the client-side
@@ -4365,7 +3964,7 @@
             // There are clients waiting to receive thumbnails so, in case
             // this is an activity that someone is waiting for, add it
             // to the pending list so we can correctly update the clients.
-            mCancelledThumbnails.add(r);
+            mService.mCancelledThumbnails.add(r);
         }
 
         // Get rid of any pending idle timeouts.
@@ -4388,10 +3987,6 @@
             here.fillInStackTrace();
             Slog.i(TAG, "Removing activity " + r + " from stack");
         }
-        final TaskRecord task = r.task;
-        if (task != null) {
-            task.removeActivity(r);
-        }
         mHistory.remove(r);
         r.takeFromHistory();
         removeTimeoutsForActivityLocked(r);
@@ -4576,7 +4171,7 @@
                     mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
                 }
 
-                int index = mHistory.indexOf(r);
+                int index = indexOfActivityLocked(r);
                 if (index >= 0) {
                     if (r.state == ActivityState.DESTROYING) {
                         cleanUpActivityLocked(r, true, false);
@@ -4590,15 +4185,15 @@
         }
     }
     
-    private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
-            ProcessRecord app, String listName) {
+    private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app,
+            String listName) {
         int i = list.size();
         if (DEBUG_CLEANUP) Slog.v(
             TAG, "Removing app " + app + " from list " + listName
             + " with " + i + " entries");
         while (i > 0) {
             i--;
-            ActivityRecord r = list.get(i);
+            ActivityRecord r = (ActivityRecord)list.get(i);
             if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
             if (r.app == app) {
                 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
@@ -4624,7 +4219,7 @@
             TAG, "Removing app " + app + " from history with " + i + " entries");
         while (i > 0) {
             i--;
-            ActivityRecord r = mHistory.get(i);
+            ActivityRecord r = (ActivityRecord)mHistory.get(i);
             if (DEBUG_CLEANUP) Slog.v(
                 TAG, "Record #" + i + " " + r + ": app=" + r.app);
             if (r.app == app) {
@@ -4692,7 +4287,6 @@
      * of the stack.
      */
     final void moveHomeToFrontLocked() {
-        newMoveHomeToFrontLocked();
         TaskRecord homeTask = null;
         for (int i=mHistory.size()-1; i>=0; i--) {
             ActivityRecord hr = mHistory.get(i);
@@ -4702,23 +4296,6 @@
             }
         }
         if (homeTask != null) {
-//            moveTaskToFrontLocked(homeTask, null, null);
-        }
-    }
-
-    final void newMoveHomeToFrontLocked() {
-        TaskRecord homeTask = null;
-        for (int taskNdx = mTaskHistory.size() - 1; homeTask == null && taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
-                if (r.isHomeActivity) {
-                    homeTask = r.task;
-                    break;
-                }
-            }
-        }
-        if (homeTask != null) {
             moveTaskToFrontLocked(homeTask, null, null);
         }
     }
@@ -4735,39 +4312,32 @@
         mService.mWindowManager.prepareAppTransition(transit, false);
     }
 
-    final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
-        for (int i = mHistory.size() - 1; i >= 0; i--) {
-            ActivityRecord hr = mHistory.get(i);
-            if (hr.task.taskId == taskId) {
-                if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
-                    mUserLeaving = true;
-                }
-                if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
-                    // Caller wants the home activity moved with it.  To accomplish this,
-                    // we'll just move the home task to the top first.
-                    moveHomeToFrontLocked();
-                }
-                moveTaskToFrontLocked(hr.task, null, options);
-                return true;
-            }
-        }
-        return false;
-    }
-
     final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
+        if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
 
         final int task = tr.taskId;
         int top = mHistory.size()-1;
 
         if (top < 0 || (mHistory.get(top)).task.taskId == task) {
             // nothing to do!
+            if (reason != null &&
+                    (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+                ActivityOptions.abort(options);
+            } else {
+                updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
+            }
             return;
         }
 
+        ArrayList<IBinder> moved = new ArrayList<IBinder>();
+
+        // Applying the affinities may have removed entries from the history,
+        // so get the size again.
+        top = mHistory.size()-1;
+        int pos = top;
 
         // Shift all activities with this task up to the top
         // of the stack, keeping them in the same internal order.
-        int pos = top;
         while (pos >= 0) {
             ActivityRecord r = mHistory.get(pos);
             if (localLOGV) Slog.v(
@@ -4781,37 +4351,18 @@
                 }
                 mHistory.remove(pos);
                 mHistory.add(top, r);
+                moved.add(0, r.appToken);
                 top--;
             }
             pos--;
         }
-        //
-        // Start new code here! Delete everything above.
-        //
-        if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
 
-        final int numTasks = mTaskHistory.size();
-        final int index = mTaskHistory.indexOf(tr);
-        if (numTasks == 0 || index < 0 || index == numTasks - 1)  {
-            // nothing to do!
-            if (reason != null &&
-                    (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
-                ActivityOptions.abort(options);
-            } else {
-                updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
-            }
-            return;
-        }
-
-        // Shift all activities with this task up to the top
-        // of the stack, keeping them in the same internal order.
-        mTaskHistory.remove(tr);
-        mTaskHistory.add(tr);
-
-        if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
+        if (DEBUG_TRANSITION) Slog.v(TAG,
+                "Prepare to front transition: task=" + tr);
         if (reason != null &&
                 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
-            mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+            mService.mWindowManager.prepareAppTransition(
+                    AppTransition.TRANSIT_NONE, false);
             ActivityRecord r = topRunningActivityLocked(null);
             if (r != null) {
                 mNoAnimActivities.add(r);
@@ -4820,18 +4371,14 @@
         } else {
             updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
         }
-
-        mService.mWindowManager.moveTaskToTop(task);
-
-        finishTaskMoveLocked(task);
-        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
-
+        
+        mService.mWindowManager.moveAppTokensToTop(moved);
         if (VALIDATE_TOKENS) {
             validateAppTokensLocked();
         }
-        if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords(true);
-        }
+
+        finishTaskMoveLocked(task);
+        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
     }
 
     private final void finishTaskMoveLocked(int task) {
@@ -4851,7 +4398,7 @@
      */
     final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
         Slog.i(TAG, "moveTaskToBack: " + task);
-
+        
         // If we have a watcher, preflight the move before committing to it.  First check
         // for *other* available tasks, but if none are available, then try again allowing the
         // current task to be selected.
@@ -4874,14 +4421,11 @@
             }
         }
 
+        ArrayList<IBinder> moved = new ArrayList<IBinder>();
+
         if (DEBUG_TRANSITION) Slog.v(TAG,
                 "Prepare to back transition: task=" + task);
-
-        final TaskRecord tr = mTaskIdToTaskRecord.get(task);
-        mTaskHistory.remove(tr);
-        mTaskHistory.add(0, tr);
-
-        // BEGIN REGION TO REMOVE.
+        
         final int N = mHistory.size();
         int bottom = 0;
         int pos = 0;
@@ -4902,18 +4446,16 @@
                 }
                 mHistory.remove(pos);
                 mHistory.add(bottom, r);
+                moved.add(r.appToken);
                 bottom++;
             }
             pos++;
         }
-        if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords(true);
-        }
-        // END REGION TO REMOVE
 
         if (reason != null &&
                 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
-            mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+            mService.mWindowManager.prepareAppTransition(
+                    AppTransition.TRANSIT_NONE, false);
             ActivityRecord r = topRunningActivityLocked(null);
             if (r != null) {
                 mNoAnimActivities.add(r);
@@ -4922,8 +4464,7 @@
             mService.mWindowManager.prepareAppTransition(
                     AppTransition.TRANSIT_TASK_TO_BACK, false);
         }
-        mService.mWindowManager.moveTaskToBottom(task);
-
+        mService.mWindowManager.moveAppTokensToBottom(moved);
         if (VALIDATE_TOKENS) {
             validateAppTokensLocked();
         }
@@ -4956,8 +4497,9 @@
         TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
         if (info.numSubThumbbails <= 0) {
             return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
+        } else {
+            return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
         }
-        return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
     }
 
     public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
@@ -5037,7 +4579,6 @@
         }
         if (thumbs.numSubThumbbails > 0) {
             thumbs.retriever = new IThumbnailRetriever.Stub() {
-                @Override
                 public Bitmap getThumbnail(int index) {
                     if (index < 0 || index >= thumbs.subtasks.size()) {
                         return null;
@@ -5236,283 +4777,4 @@
     public void dismissKeyguardOnNextActivityLocked() {
         mDismissKeyguardOnNextActivity = true;
     }
-
-    boolean willActivityBeVisibleLocked(IBinder token) {
-        int i;
-        for (i = mHistory.size() - 1; i >= 0; i--) {
-            ActivityRecord r = mHistory.get(i);
-            if (r.appToken == token) {
-                    return true;
-            }
-            if (r.fullscreen && !r.finishing) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    void closeSystemDialogsLocked() {
-        for (int i = mHistory.size() - 1; i >= 0; i--) {
-            ActivityRecord r = mHistory.get(i);
-            if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
-                r.stack.finishActivityLocked(r, i,
-                        Activity.RESULT_CANCELED, null, "close-sys", true);
-            }
-        }
-    }
-
-    boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
-        boolean didSomething = false;
-        TaskRecord lastTask = null;
-        final int N = mHistory.size();
-        for (int i = 0; i < N; i++) {
-            ActivityRecord r = mHistory.get(i);
-            final boolean samePackage = r.packageName.equals(name)
-                    || (name == null && r.userId == userId);
-            if ((userId == UserHandle.USER_ALL || r.userId == userId)
-                    && (samePackage || r.task == lastTask)
-                    && (r.app == null || evenPersistent || !r.app.persistent)) {
-                if (!doit) {
-                    if (r.finishing) {
-                        // If this activity is just finishing, then it is not
-                        // interesting as far as something to stop.
-                        continue;
-                    }
-                    return true;
-                }
-                didSomething = true;
-                Slog.i(TAG, "  Force finishing activity " + r);
-                if (samePackage) {
-                    if (r.app != null) {
-                        r.app.removed = true;
-                    }
-                    r.app = null;
-                }
-                lastTask = r.task;
-                if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
-                        null, "force-stop", true)) {
-                    i--;
-                }
-            }
-        }
-        return didSomething;
-    }
-
-    ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
-        PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
-        ActivityRecord topRecord = null;
-        int pos = mHistory.size() - 1;
-        ActivityRecord next = pos >= 0 ? mHistory.get(pos) : null;
-        ActivityRecord top = null;
-        TaskRecord curTask = null;
-        int numActivities = 0;
-        int numRunning = 0;
-        while (pos >= 0 && maxNum > 0) {
-            final ActivityRecord r = next;
-            pos--;
-            next = pos >= 0 ? mHistory.get(pos) : null;
-
-            // Initialize state for next task if needed.
-            if (top == null || (top.state == ActivityState.INITIALIZING && top.task == r.task)) {
-                top = r;
-                curTask = r.task;
-                numActivities = numRunning = 0;
-            }
-
-            // Add 'r' into the current task.
-            numActivities++;
-            if (r.app != null && r.app.thread != null) {
-                numRunning++;
-            }
-
-            if (localLOGV) Slog.v(
-                TAG, r.intent.getComponent().flattenToShortString()
-                + ": task=" + r.task);
-
-            // If the next one is a different task, generate a new
-            // TaskInfo entry for what we have.
-            if (next == null || next.task != curTask) {
-                RunningTaskInfo ci = new RunningTaskInfo();
-                ci.id = curTask.taskId;
-                ci.baseActivity = r.intent.getComponent();
-                ci.topActivity = top.intent.getComponent();
-                if (top.thumbHolder != null) {
-                    ci.description = top.thumbHolder.lastDescription;
-                }
-                ci.numActivities = numActivities;
-                ci.numRunning = numRunning;
-                //System.out.println(
-                //    "#" + maxNum + ": " + " descr=" + ci.description);
-                if (receiver != null) {
-                    if (localLOGV) Slog.v(
-                        TAG, "State=" + top.state + "Idle=" + top.idle
-                        + " app=" + top.app
-                        + " thr=" + (top.app != null ? top.app.thread : null));
-                    if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
-                        if (top.idle && top.app != null && top.app.thread != null) {
-                            topRecord = top;
-                        } else {
-                            top.thumbnailNeeded = true;
-                        }
-                    }
-                    pending.pendingRecords.add(top);
-                }
-                list.add(ci);
-                maxNum--;
-                top = null;
-            }
-        }
-        return topRecord;
-    }
-
-    public void unhandledBackLocked() {
-        int top = mHistory.size() - 1;
-        if (DEBUG_SWITCH) Slog.d(
-            TAG, "Performing unhandledBack(): top activity at " + top);
-        if (top > 0) {
-            finishActivityLocked(mHistory.get(top),
-                        top, Activity.RESULT_CANCELED, null, "unhandled-back", true);
-        }
-    }
-
-    void handleAppCrashLocked(ProcessRecord app) {
-        for (int i = mHistory.size() - 1; i >= 0; i--) {
-            ActivityRecord r = mHistory.get(i);
-            if (r.app == app) {
-                Slog.w(TAG, "  Force finishing activity "
-                    + r.intent.getComponent().flattenToShortString());
-                r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
-                        null, "crashed", false);
-            }
-        }
-    }
-
-    void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
-            boolean dumpClient, String dumpPackage) {
-        ActivityManagerService.dumpHistoryList(fd, pw, mHistory, "  ", "Hist", true, !dumpAll,
-            dumpClient, dumpPackage);
-    }
-
-    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
-        ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
-
-        if ("all".equals(name)) {
-            for (ActivityRecord r1 : mHistory) {
-                activities.add(r1);
-            }
-        } else if ("top".equals(name)) {
-            final int N = mHistory.size();
-            if (N > 0) {
-                activities.add(mHistory.get(N-1));
-            }
-        } else {
-            ItemMatcher matcher = new ItemMatcher();
-            matcher.build(name);
-
-            for (ActivityRecord r1 : mHistory) {
-                if (matcher.match(r1, r1.intent.getComponent())) {
-                    activities.add(r1);
-                }
-            }
-        }
-
-        return activities;
-    }
-
-    ActivityRecord restartPackage(String packageName) {
-        ActivityRecord starting = topRunningActivityLocked(null);
-
-        // All activities that came from the package must be
-        // restarted as if there was a config change.
-        for (int i = mHistory.size() - 1; i >= 0; i--) {
-            ActivityRecord a = mHistory.get(i);
-            if (a.info.packageName.equals(packageName)) {
-                a.forceNewConfig = true;
-                if (starting != null && a == starting && a.visible) {
-                    a.startFreezingScreenLocked(starting.app, ActivityInfo.CONFIG_SCREEN_LAYOUT);
-                }
-            }
-        }
-
-        return starting;
-    }
-
-    void rebuildTaskHistory() {
-        mTaskHistory.clear();
-        final int numActivities = mHistory.size();
-        TaskRecord task = null;
-        for (int i = 0; i < numActivities; ++i) {
-            final ActivityRecord r = mHistory.get(i);
-            if (r.task != task) {
-                task = r.task;
-                task.mActivities.clear();
-                mTaskHistory.add(task);
-            }
-            task.mActivities.add(r);
-        }
-    }
-
-    boolean verifyActivityRecords(boolean rebuild) {
-        final int numHistory = mHistory.size();
-        int historyNdx = 0;
-
-        final int numTasks = mTaskHistory.size();
-        int taskNdx;
-        for (taskNdx = historyNdx = 0; taskNdx < numTasks; ++taskNdx) {
-            final TaskRecord task = mTaskHistory.get(taskNdx);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            final int numActivities = activities.size();
-            int activityNdx;
-            for (activityNdx = 0;
-                    activityNdx < numActivities && historyNdx < numHistory;
-                    ++activityNdx, ++historyNdx) {
-                ActivityRecord r1 = mHistory.get(historyNdx);
-                ActivityRecord r2 = activities.get(activityNdx);
-                if (r1 != r2) {
-                    break;
-                }
-            }
-            if (activityNdx != numActivities) {
-                // either a mismatch or mHistory ran out before mTaskHistory.
-                break;
-            }
-        }
-        if (taskNdx != numTasks || historyNdx != numHistory) {
-            logHistories("verifyActivityRecords", rebuild);
-            return true;
-        }
-        return false;
-    }
-
-    private void logHistories(String caller, boolean rebuild) {
-        Slog.w(TAG, "Mismatch! " + caller + "  mHistory=" + mHistory);
-        ArrayList<ArrayList<ActivityRecord>> nestedRecords =
-                new ArrayList<ArrayList<ActivityRecord>>();
-        for (TaskRecord task : mTaskHistory) {
-            nestedRecords.add(task.mActivities);
-        }
-        Slog.w(TAG, "Mismatch! " + caller + " mTaskHistory" + nestedRecords);
-        Slog.w(TAG, "Mismatch! " + caller + " lastHistoryModifier=" + mLastHistoryModifier
-                + " Caller=" + Debug.getCallers(4));
-        if (rebuild) {
-            rebuildTaskHistory();
-        }
-    }
-
-    private TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
-            boolean toTop) {
-        TaskRecord oldTask = mTaskIdToTaskRecord.get(taskId);
-        if (oldTask != null) {
-            Slog.w(TAG, "createTaskRecord: Reusing taskId=" + taskId + " without removing");
-            mTaskHistory.remove(oldTask);
-        }
-        TaskRecord task = new TaskRecord(taskId, info, intent);
-        mTaskIdToTaskRecord.put(taskId, task);
-        if (toTop) {
-            mTaskHistory.add(task);
-        } else {
-            mTaskHistory.add(0, task);
-        }
-        return task;
-    }
 }
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index 863bdad..3a6492e 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -295,8 +295,20 @@
             Message msg = mHandler.obtainMessage(MSG_WRITE);
             mHandler.sendMessageDelayed(msg, 10000);
 
-            
-            ActivityRecord starting = mService.mMainStack.restartPackage(packageName);
+            ActivityRecord starting = mService.mMainStack.topRunningActivityLocked(null);
+
+            // All activities that came from the package must be
+            // restarted as if there was a config change.
+            for (int i=mService.mMainStack.mHistory.size()-1; i>=0; i--) {
+                ActivityRecord a = (ActivityRecord)mService.mMainStack.mHistory.get(i);
+                if (a.info.packageName.equals(packageName)) {
+                    a.forceNewConfig = true;
+                    if (starting != null && a == starting && a.visible) {
+                        a.startFreezingScreenLocked(starting.app,
+                                ActivityInfo.CONFIG_SCREEN_LAYOUT);
+                    }
+                }
+            }
 
             // Tell all processes that loaded this package about the change.
             for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
diff --git a/services/java/com/android/server/am/PendingThumbnailsRecord.java b/services/java/com/android/server/am/PendingThumbnailsRecord.java
index c460791..ed478c9 100644
--- a/services/java/com/android/server/am/PendingThumbnailsRecord.java
+++ b/services/java/com/android/server/am/PendingThumbnailsRecord.java
@@ -27,13 +27,13 @@
 class PendingThumbnailsRecord
 {
     final IThumbnailReceiver receiver;   // who is waiting.
-    final HashSet<ActivityRecord> pendingRecords; // HistoryRecord objects we still wait for.
+    HashSet pendingRecords; // HistoryRecord objects we still wait for.
     boolean finished;       // Is pendingRecords empty?
 
     PendingThumbnailsRecord(IThumbnailReceiver _receiver)
     {
         receiver = _receiver;
-        pendingRecords = new HashSet<ActivityRecord>();
+        pendingRecords = new HashSet();
         finished = false;
     }
 }
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index f9b0d4c..1bae9ca 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -23,7 +23,6 @@
 import android.util.Slog;
 
 import java.io.PrintWriter;
-import java.util.ArrayList;
 
 class TaskRecord extends ThumbnailHolder {
     final int taskId;       // Unique identifier for this task.
@@ -40,11 +39,7 @@
 
     String stringName;      // caching of toString() result.
     int userId;             // user for which this task was created
-
-    int numFullscreen;      // Number of fullscreen activities.
-
-    final ArrayList<ActivityRecord> mActivities = new ArrayList<ActivityRecord>();
-
+    
     TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
         taskId = _taskId;
         affinity = info.taskAffinity;
@@ -109,63 +104,12 @@
             userId = UserHandle.getUserId(info.applicationInfo.uid);
         }
     }
-
-    ActivityRecord getTopActivity() {
-        for (int i = mActivities.size() - 1; i >= 0; --i) {
-            final ActivityRecord r = mActivities.get(i);
-            if (r.finishing) {
-                continue;
-            }
-            return r;
-        }
-        return null;
-    }
-
-    void addActivityAtBottom(ActivityRecord r) {
-        if (!mActivities.remove(r) && r.fullscreen) {
-            // Was not previously in list.
-            numFullscreen++;
-        }
-        mActivities.add(0, r);
-    }
-
-    void addActivityToTop(ActivityRecord r) {
-        if (!mActivities.remove(r) && r.fullscreen) {
-            // Was not previously in list.
-            numFullscreen++;
-        }
-        // TODO: This only matters to achieve identical results as mHistory. Later we won't need
-        // to skip over finishing activities.
-        int i;
-        for (i = mActivities.size() - 1; i >= 0; --i) {
-            if (!mActivities.get(i).finishing) {
-                break;
-            }
-        }
-        if (i >= 0) {
-            // Add below finishing activities.
-            mActivities.add(i + 1, r);
-        } else {
-            // All activities are finishing, add to top.
-            mActivities.add(r);
-        }
-    }
-
-    /** @return true if this was the last activity in the task */
-    boolean removeActivity(ActivityRecord r) {
-        if (mActivities.remove(r) && r.fullscreen) {
-            // Was previously in list.
-            numFullscreen--;
-        }
-        return mActivities.size() == 0;
-    }
-
+    
     void dump(PrintWriter pw, String prefix) {
         if (numActivities != 0 || rootWasReset || userId != 0) {
             pw.print(prefix); pw.print("numActivities="); pw.print(numActivities);
                     pw.print(" rootWasReset="); pw.print(rootWasReset);
-                    pw.print(" userId="); pw.print(userId);
-                    pw.print(" numFullscreen="); pw.println(numFullscreen);
+                    pw.print(" userId="); pw.println(userId);
         }
         if (affinity != null) {
             pw.print(prefix); pw.print("affinity="); pw.println(affinity);
@@ -192,7 +136,6 @@
             pw.print(prefix); pw.print("realActivity=");
             pw.println(realActivity.flattenToShortString());
         }
-        pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
         if (!askedCompatMode) {
             pw.print(prefix); pw.print("askedCompatMode="); pw.println(askedCompatMode);
         }
@@ -203,7 +146,6 @@
                 pw.print((getInactiveDuration()/1000)); pw.println("s)");
     }
 
-    @Override
     public String toString() {
         if (stringName != null) {
             return stringName;
@@ -214,21 +156,19 @@
         sb.append(" #");
         sb.append(taskId);
         if (affinity != null) {
-            sb.append(" A=");
+            sb.append(" A ");
             sb.append(affinity);
         } else if (intent != null) {
-            sb.append(" I=");
+            sb.append(" I ");
             sb.append(intent.getComponent().flattenToShortString());
         } else if (affinityIntent != null) {
-            sb.append(" aI=");
+            sb.append(" aI ");
             sb.append(affinityIntent.getComponent().flattenToShortString());
         } else {
             sb.append(" ??");
         }
-        sb.append(" U=");
+        sb.append(" U ");
         sb.append(userId);
-        sb.append(" sz=");
-        sb.append(mActivities.size());
         sb.append('}');
         return stringName = sb.toString();
     }
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 8cc1d02..fbb5013 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -30,10 +30,6 @@
 import android.view.WindowManager;
 
 import java.io.PrintWriter;
-import java.util.ArrayList;
-
-class AppTokenList extends ArrayList<AppWindowToken> {
-}
 
 /**
  * Version of WindowToken that is specifically for a particular application (or
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 6aae202..59e4b0e 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -16,17 +16,11 @@
 
 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> {
 }
@@ -39,7 +33,6 @@
  * WindowManagerService.mWindowMap.
  */
 class DisplayContent {
-//    private final static String TAG = "DisplayContent";
 
     /** Unique identifier of this stack. */
     private final int mDisplayId;
@@ -74,26 +67,6 @@
     final boolean isDefaultDisplay;
 
     /**
-     * Window tokens that are in the process of exiting, but still
-     * on screen for animations.
-     */
-    final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
-
-    /**
-     * Application tokens that are in the process of exiting, but still
-     * on screen for animations.
-     */
-    final AppTokenList mExitingAppTokens = new AppTokenList();
-
-    /**
-     * Sorted most recent at top, oldest at [0].
-     */
-    ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>();
-    SparseArray<TaskList> mTaskIdToTaskList = new SparseArray<TaskList>();
-
-    private final AppTokenIterator mTmpAppIterator = new AppTokenIterator();
-
-    /**
      * @param display May not be null.
      */
     DisplayContent(Display display) {
@@ -123,147 +96,6 @@
         mDisplay.getDisplayInfo(mDisplayInfo);
     }
 
-    /**
-     *  Find the location to insert a new AppWindowToken into the window-ordered app token list.
-     * @param addPos The location the token was inserted into in mAppTokens.
-     * @param wtoken The token to insert.
-     */
-    void addAppToken(final int addPos, final AppWindowToken wtoken) {
-        TaskList task = mTaskIdToTaskList.get(wtoken.groupId);
-        if (task == null) {
-            task = new TaskList(wtoken, this);
-            mTaskIdToTaskList.put(wtoken.groupId, task);
-            mTaskLists.add(task);
-        } else {
-            task.mAppTokens.add(addPos, wtoken);
-        }
-    }
-
-    void removeAppToken(final AppWindowToken wtoken) {
-        final int taskId = wtoken.groupId;
-        final TaskList task = mTaskIdToTaskList.get(taskId);
-        if (task != null) {
-            AppTokenList appTokens = task.mAppTokens;
-            appTokens.remove(wtoken);
-            if (appTokens.size() == 0) {
-                mTaskLists.remove(task);
-                mTaskIdToTaskList.delete(taskId);
-            }
-        }
-    }
-
-    void setAppTaskId(AppWindowToken wtoken, int newTaskId) {
-        final int taskId = wtoken.groupId;
-        TaskList task = mTaskIdToTaskList.get(taskId);
-        if (task != null) {
-            AppTokenList appTokens = task.mAppTokens;
-            appTokens.remove(wtoken);
-            if (appTokens.size() == 0) {
-                mTaskIdToTaskList.delete(taskId);
-            }
-        }
-
-        task = mTaskIdToTaskList.get(newTaskId);
-        if (task == null) {
-            task = new TaskList(wtoken, this);
-            mTaskIdToTaskList.put(newTaskId, task);
-        } else {
-            task.mAppTokens.add(wtoken);
-        }
-
-        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);
-        }
-
-        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();
-        }
-    }
-
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
         final String subPrefix = "  " + prefix;
@@ -287,51 +119,7 @@
             pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
             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) {
-                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, "    ");
-                }
-            }
-            if (mExitingTokens.size() > 0) {
-                pw.println();
-                pw.println("  Exiting tokens:");
-                for (int i=mExitingTokens.size()-1; i>=0; i--) {
-                    WindowToken token = mExitingTokens.get(i);
-                    pw.print("  Exiting #"); pw.print(i);
-                    pw.print(' '); pw.print(token);
-                    pw.println(':');
-                    token.dump(pw, "    ");
-                }
-            }
-            if (mExitingAppTokens.size() > 0) {
-                pw.println();
-                pw.println("  Exiting application tokens:");
-                for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
-                    WindowToken token = mExitingAppTokens.get(i);
-                    pw.print("  Exiting App #"); pw.print(i);
-                      pw.print(' '); pw.print(token);
-                      pw.println(':');
-                      token.dump(pw, "    ");
-                }
-            }
-            if (mTaskIdToTaskList.size() > 0) {
-                pw.println();
-                for (int i = 0; i < mTaskIdToTaskList.size(); ++i) {
-                    pw.print("  TaskList #"); pw.print(i);
-                      pw.print(" taskId="); pw.println(mTaskIdToTaskList.keyAt(i));
-                    pw.print("    mAppTokens=");
-                      pw.println(mTaskIdToTaskList.valueAt(i).mAppTokens);
-                    pw.println();
-                }
-            }
+        pw.print(subPrefix); pw.print("layoutNeeded="); pw.print(layoutNeeded);
         pw.println();
     }
 }
diff --git a/services/java/com/android/server/wm/TaskGroup.java b/services/java/com/android/server/wm/TaskGroup.java
deleted file mode 100644
index 1f1dd58..0000000
--- a/services/java/com/android/server/wm/TaskGroup.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import android.view.IApplicationToken;
-
-import java.util.ArrayList;
-
-public class TaskGroup {
-    public int taskId = -1;
-    public ArrayList<IApplicationToken> tokens = new ArrayList<IApplicationToken>();
-
-    @Override
-    public String toString() {
-        return "id=" + taskId + " tokens=" + tokens;
-    }
-}
diff --git a/services/java/com/android/server/wm/TaskList.java b/services/java/com/android/server/wm/TaskList.java
deleted file mode 100644
index 67dfa4f..0000000
--- a/services/java/com/android/server/wm/TaskList.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-class TaskList {
-//    private final String TAG = "TaskGroup";
-    DisplayContent mDisplayContent;
-    final AppTokenList mAppTokens = new AppTokenList();
-    final int taskId;
-
-    TaskList(AppWindowToken wtoken, DisplayContent displayContent) {
-        taskId = wtoken.groupId;
-        mAppTokens.add(wtoken);
-        mDisplayContent = displayContent;
-    }
-
-    @Override
-    public String toString() {
-        return "id=" + taskId + " appTokens=" + mAppTokens;
-    }
-}
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 67daf75..3964782 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;
@@ -28,7 +26,6 @@
 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;
 
@@ -175,12 +172,12 @@
         }
     }
 
-    private void updateAppWindowsLocked(int displayId) {
+    private void updateAppWindowsLocked() {
         int i;
-        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
-        while (iterator.hasNext()) {
-            final AppWindowAnimator appAnimator = iterator.next().mAppAnimator;
+        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
+        final int NAT = appTokens.size();
+        for (i=0; i<NAT; i++) {
+            final AppWindowAnimator appAnimator = appTokens.get(i).mAppAnimator;
             final boolean wasAnimating = appAnimator.animation != null
                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
             if (appAnimator.stepAnimationLocked(mCurrentTime)) {
@@ -194,10 +191,9 @@
             }
         }
 
-        final AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
-        final int NEAT = exitingAppTokens.size();
+        final int NEAT = mService.mExitingAppTokens.size();
         for (i=0; i<NEAT; i++) {
-            final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
+            final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator;
             final boolean wasAnimating = appAnimator.animation != null
                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
             if (appAnimator.stepAnimationLocked(mCurrentTime)) {
@@ -458,13 +454,13 @@
 
     /** See if any windows have been drawn, so they (and others associated with them) can now be
      *  shown. */
-    private void testTokenMayBeDrawnLocked(int displayId) {
+    private void testTokenMayBeDrawnLocked() {
         // 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();
+        final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
+        final int NT = appTokens.size();
+        for (int i=0; i<NT; i++) {
+            AppWindowToken wtoken = appTokens.get(i);
             AppWindowAnimator appAnimator = wtoken.mAppAnimator;
             final boolean allDrawn = wtoken.allDrawn;
             if (allDrawn != appAnimator.allDrawn) {
@@ -534,10 +530,11 @@
         SurfaceControl.openTransaction();
         SurfaceControl.setAnimationTransaction();
         try {
+            updateAppWindowsLocked();
+
             final int numDisplays = mDisplayContentsAnimators.size();
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-                updateAppWindowsLocked(displayId);
                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
                 final ScreenRotationAnimation screenRotationAnimation =
@@ -563,11 +560,10 @@
                 }
             }
 
+            testTokenMayBeDrawnLocked();
+
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-
-                testTokenMayBeDrawnLocked(displayId);
-
                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
                 final ScreenRotationAnimation screenRotationAnimation =
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 086da37..a6ce54c 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;
@@ -182,7 +181,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;
@@ -198,7 +197,6 @@
     static final boolean DEBUG_LAYOUT_REPEATS = true;
     static final boolean DEBUG_SURFACE_TRACE = false;
     static final boolean DEBUG_WINDOW_TRACE = false;
-    static final boolean DEBUG_TASK_MOVEMENT = false;
     static final boolean SHOW_SURFACE_ALLOC = false;
     static final boolean SHOW_TRANSACTIONS = false;
     static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
@@ -208,9 +206,6 @@
     static final boolean PROFILE_ORIENTATION = false;
     static final boolean localLOGV = DEBUG;
 
-    final static boolean REVERSE_ITERATOR = true;
-    final static boolean FORWARD_ITERATOR = false;
-
     /** How much to multiply the policy's type layer, to reserve room
      * for multiple windows of the same type and Z-ordering adjustment
      * with TYPE_LAYER_OFFSET. */
@@ -337,7 +332,34 @@
     /**
      * Mapping from a token IBinder to a WindowToken object.
      */
-    final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
+    final HashMap<IBinder, WindowToken> mTokenMap =
+            new HashMap<IBinder, WindowToken>();
+
+    /**
+     * Window tokens that are in the process of exiting, but still
+     * on screen for animations.
+     */
+    final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
+
+    /**
+     * List controlling the ordering of windows in different applications which must
+     * be kept in sync with ActivityManager.
+     */
+    final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
+
+    /**
+     * AppWindowTokens in the Z order they were in at the start of an animation. Between
+     * animations this list is maintained in the exact order of mAppTokens. If tokens
+     * are added to mAppTokens during an animation an attempt is made to insert them at the same
+     * logical location in this list. Note that this list is always in sync with mWindows.
+     */
+    ArrayList<AppWindowToken> mAnimatingAppTokens = new ArrayList<AppWindowToken>();
+
+    /**
+     * Application tokens that are in the process of exiting, but still
+     * on screen for animations.
+     */
+    final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
 
     /**
      * List of window tokens that have finished starting their application,
@@ -422,12 +444,8 @@
 
     String mLastANRState;
 
-    /** All DisplayContents in the world, kept here */
+    /** All DisplayDontents in the world, kept here */
     private SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>();
-    private SparseArray<DisplayContent> mTaskIdToDisplayContents =
-            new SparseArray<DisplayContent>();
-
-    private final AllWindowsIterator mTmpWindowsIterator = new AllWindowsIterator();
 
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -901,6 +919,7 @@
         final WindowList windows = win.getWindowList();
         final int N = windows.size();
         final WindowState attached = win.mAttachedWindow;
+        int i;
         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
         if (attached == null) {
             int tokenWindowsPos = 0;
@@ -950,11 +969,12 @@
                         + client.asBinder() + " (token=" + token + ")");
                     // Figure out where the window should go, based on the
                     // order of applications.
+                    final int NA = mAnimatingAppTokens.size();
                     WindowState pos = null;
-                    AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-                    while (iterator.hasNext()) {
-                        AppWindowToken t = iterator.next();
+                    for (i=NA-1; i>=0; i--) {
+                        AppWindowToken t = mAnimatingAppTokens.get(i);
                         if (t == token) {
+                            i--;
                             break;
                         }
 
@@ -987,14 +1007,15 @@
                     } 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);
+                        while (i >= 0) {
+                            AppWindowToken t = mAnimatingAppTokens.get(i);
+                            tokenWindowList = getTokenWindowsOnDisplay(t, win.mDisplayContent);
                             final int NW = tokenWindowList.size();
                             if (NW > 0) {
                                 pos = tokenWindowList.get(NW-1);
                                 break;
                             }
+                            i--;
                         }
                         if (pos != null) {
                             // Move in front of any windows attached to this
@@ -1013,8 +1034,7 @@
                         } else {
                             // Just search for the start of this layer.
                             final int myLayer = win.mBaseLayer;
-                            int i;
-                            for (i = 0; i < N; i++) {
+                            for (i=0; i<N; i++) {
                                 WindowState w = windows.get(i);
                                 if (w.mBaseLayer > myLayer) {
                                     break;
@@ -1032,8 +1052,7 @@
             } else {
                 // Figure out where window should go, based on layer.
                 final int myLayer = win.mBaseLayer;
-                int i;
-                for (i = N - 1; i >= 0; i--) {
+                for (i=N-1; i>=0; i--) {
                     if (windows.get(i).mBaseLayer <= myLayer) {
                         break;
                     }
@@ -1058,8 +1077,7 @@
             final int sublayer = win.mSubLayer;
             int largestSublayer = Integer.MIN_VALUE;
             WindowState windowWithLargestSublayer = null;
-            int i;
-            for (i = 0; i < NA; i++) {
+            for (i=0; i<NA; i++) {
                 WindowState w = tokenWindowList.get(i);
                 final int wSublayer = w.mSubLayer;
                 if (wSublayer >= largestSublayer) {
@@ -2464,15 +2482,22 @@
 
     public void updateAppOpsState() {
         synchronized(mWindowMap) {
-            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
-            while (mTmpWindowsIterator.hasNext()) {
-                final WindowState win = mTmpWindowsIterator.next();
-                if (win.mAppOp != AppOpsManager.OP_NONE) {
-                    final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
-                            win.getOwningPackage());
-                    win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
+            boolean changed = false;
+            for (int i=0; i<mDisplayContents.size(); i++) {
+                DisplayContent display = mDisplayContents.valueAt(i);
+                WindowList windows = display.getWindowList();
+                for (int j=0; j<windows.size(); j++) {
+                    final WindowState win = windows.get(j);
+                    if (win.mAppOp != AppOpsManager.OP_NONE) {
+                        changed |= win.setAppOpVisibilityLw(mAppOps.checkOpNoThrow(win.mAppOp,
+                                win.getOwningUid(),
+                                win.getOwningPackage()) == AppOpsManager.MODE_ALLOWED);
+                    }
                 }
             }
+            if (changed) {
+                scheduleAnimationLocked();
+            }
         }
     }
 
@@ -3112,58 +3137,32 @@
     // Application Window Tokens
     // -------------------------------------------------------------
 
-    public void validateAppTokens(List<TaskGroup> tasks) {
-        synchronized (mWindowMap) {
-            int t = tasks.size() - 1;
-            if (t < 0) {
-                Slog.w(TAG, "validateAppTokens: empty task list");
-                return;
+    public void validateAppTokens(List<IBinder> tokens) {
+        int v = tokens.size()-1;
+        int m = mAppTokens.size()-1;
+        while (v >= 0 && m >= 0) {
+            AppWindowToken atoken = mAppTokens.get(m);
+            if (atoken.removed) {
+                m--;
+                continue;
             }
-
-            TaskGroup task = tasks.get(0);
-            int taskId = task.taskId;
-            DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
-            if (displayContent == null) {
-                Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
-                return;
+            if (tokens.get(v) != atoken.token) {
+                Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
+                      + " @ " + v + ", internal is " + atoken.token + " @ " + m);
             }
-
-            boolean mismatch = false;
-            AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-            for ( ; t >= 0 && !mismatch; --t) {
-                task = tasks.get(t);
-                List<IApplicationToken> tokens = task.tokens;
-                int v = task.tokens.size() - 1;
-
-                DisplayContent lastDisplayContent = displayContent;
-                displayContent = mTaskIdToDisplayContents.get(taskId);
-                if (displayContent != lastDisplayContent) {
-                    Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
-                    return;
-                }
-
-                while (v >= 0) {
-                    if (!iterator.hasNext()) {
-                        mismatch = true;
-                        break;
-                    }
-                    AppWindowToken atoken = iterator.next();
-                    if (atoken.removed) {
-                        continue;
-                    }
-                    if (tokens.get(v) != atoken.token) {
-                        mismatch = true;
-                        break;
-                    }
-                    v--;
-                }
+            v--;
+            m--;
+        }
+        while (v >= 0) {
+            Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
+            v--;
+        }
+        while (m >= 0) {
+            AppWindowToken atoken = mAppTokens.get(m);
+            if (!atoken.removed) {
+                Slog.w(TAG, "Invalid internal atoken: " + atoken.token + " @ " + m);
             }
-
-            if (mismatch || iterator.hasNext()) {
-                Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
-                Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + iterator);
-                Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
-            }
+            m--;
         }
     }
 
@@ -3227,7 +3226,6 @@
 
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
-            DisplayContent displayContent = null;
             WindowToken wtoken = mTokenMap.remove(token);
             if (wtoken != null) {
                 boolean delayed = false;
@@ -3237,7 +3235,6 @@
 
                     for (int i=0; i<N; i++) {
                         WindowState win = wtoken.windows.get(i);
-                        displayContent = win.mDisplayContent;
 
                         if (win.mWinAnimator.isAnimating()) {
                             delayed = true;
@@ -3247,12 +3244,13 @@
                             win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
                                     false);
                             //TODO (multidisplay): Magnification is supported only for the default
-                            if (mDisplayMagnifier != null && win.isDefaultDisplay()) {
+                            if (mDisplayMagnifier != null
+                                    && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
                                 mDisplayMagnifier.onWindowTransitionLocked(win,
                                         WindowManagerPolicy.TRANSIT_EXIT);
                             }
                             changed = true;
-                            displayContent.layoutNeeded = true;
+                            win.mDisplayContent.layoutNeeded = true;
                         }
                     }
 
@@ -3265,7 +3263,7 @@
                     }
 
                     if (delayed) {
-                        displayContent.mExitingTokens.add(wtoken);
+                        mExitingTokens.add(wtoken);
                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
                         mWallpaperTokens.remove(wtoken);
                     }
@@ -3279,9 +3277,27 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    /**
+     *  Find the location to insert a new AppWindowToken into the window-ordered app token list.
+     *  Note that mAppTokens.size() == mAnimatingAppTokens.size() + 1.
+     * @param addPos The location the token was inserted into in mAppTokens.
+     * @param atoken The token to insert.
+     */
+    private void addAppTokenToAnimating(final int addPos, final AppWindowToken atoken) {
+        if (addPos == 0 || addPos == mAnimatingAppTokens.size()) {
+            // It was inserted into the beginning or end of mAppTokens. Honor that.
+            mAnimatingAppTokens.add(addPos, atoken);
+            return;
+        }
+        // Find the item immediately above the mAppTokens insertion point and put the token
+        // immediately below that one in mAnimatingAppTokens.
+        final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1);
+        mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), atoken);
+    }
+
     @Override
     public void addAppToken(int addPos, IApplicationToken token,
-            int taskId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
+            int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "addAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -3309,21 +3325,15 @@
             }
             atoken = new AppWindowToken(this, token);
             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
-            atoken.groupId = taskId;
+            atoken.groupId = groupId;
             atoken.appFullscreen = fullscreen;
             atoken.showWhenLocked = showWhenLocked;
             atoken.requestedOrientation = requestedOrientation;
             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
                     + " at " + addPos);
-
-            DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
-            if (displayContent == null) {
-                displayContent = getDefaultDisplayContentLocked();
-                mTaskIdToDisplayContents.put(taskId, displayContent);
-            }
-            displayContent.addAppToken(addPos, atoken);
+            mAppTokens.add(addPos, atoken);
+            addAppTokenToAnimating(addPos, atoken);
             mTokenMap.put(token.asBinder(), atoken);
-            mTaskIdToDisplayContents.put(taskId, displayContent);
 
             // Application tokens start out hidden.
             atoken.hidden = true;
@@ -3341,17 +3351,12 @@
         }
 
         synchronized(mWindowMap) {
-            final AppWindowToken atoken = findAppWindowToken(token);
+            AppWindowToken atoken = findAppWindowToken(token);
             if (atoken == null) {
                 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
                 return;
             }
-            DisplayContent displayContent = mTaskIdToDisplayContents.get(atoken.groupId);
-            if (displayContent == null) {
-                Slog.w(TAG, "setAppGroupId: No DisplayContent for taskId=" + atoken.groupId);
-                displayContent = getDefaultDisplayContentLocked();
-            }
-            displayContent.setAppTaskId(atoken, groupId);
+            atoken.groupId = groupId;
         }
     }
 
@@ -3397,11 +3402,8 @@
         boolean findingBehind = false;
         boolean haveGroup = false;
         boolean lastFullscreen = false;
-        // TODO: Multi window.
-        DisplayContent displayContent = getDefaultDisplayContentLocked();
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-        while (iterator.hasNext()) {
-            AppWindowToken atoken = iterator.next();
+        for (int pos = mAppTokens.size() - 1; pos >= 0; pos--) {
+            AppWindowToken atoken = mAppTokens.get(pos);
 
             if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
 
@@ -4316,12 +4318,11 @@
                         TAG, "Removing app " + wtoken + " delayed=" + delayed
                         + " animation=" + wtoken.mAppAnimator.animation
                         + " animating=" + wtoken.mAppAnimator.animating);
-                DisplayContent displayContent = mTaskIdToDisplayContents.get(wtoken.groupId);
                 if (delayed) {
                     // set the token aside because it has an active animation to be finished
                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
                             "removeAppToken make exiting: " + wtoken);
-                    displayContent.mExitingAppTokens.add(wtoken);
+                    mExitingAppTokens.add(wtoken);
                 } else {
                     // Make sure there is no animation running on this token,
                     // so any windows associated with it will be removed as
@@ -4331,7 +4332,8 @@
                 }
                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
                         "removeAppToken: " + wtoken);
-                displayContent.removeAppToken(wtoken);
+                mAppTokens.remove(wtoken);
+                mAnimatingAppTokens.remove(wtoken);
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
                     startingToken = wtoken;
@@ -4383,74 +4385,78 @@
     }
 
     void dumpAppTokensLocked() {
-        DisplayContentsIterator iterator = new DisplayContentsIterator();
-        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);
-            }
+        for (int i=mAppTokens.size()-1; i>=0; i--) {
+            Slog.v(TAG, "  #" + i + ": " + mAppTokens.get(i).token);
+        }
+    }
+
+    void dumpAnimatingAppTokensLocked() {
+        for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) {
+            Slog.v(TAG, "  #" + i + ": " + mAnimatingAppTokens.get(i).token);
         }
     }
 
     void dumpWindowsLocked() {
         int i = 0;
-        mTmpWindowsIterator.reset(REVERSE_ITERATOR);
-        while (mTmpWindowsIterator.hasNext()) {
-            final WindowState w = mTmpWindowsIterator.next();
+        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState w = iterator.next();
             Slog.v(TAG, "  #" + i++ + ": " + w);
         }
     }
 
-    private int findAppWindowInsertionPointLocked(AppWindowToken target) {
-        final int taskId = target.groupId;
-        DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
-        if (displayContent == null) {
-            Slog.w(TAG, "findTopAppWindowLocked: no DisplayContent for " + target);
-            return 0;
-        }
-        final WindowList windows = displayContent.getWindowList();
+    private int findWindowOffsetLocked(WindowList windows, int tokenPos) {
         final int NW = windows.size();
 
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-        while (iterator.hasNext()) {
-            if (iterator.next() == target) {
-                break;
+        if (tokenPos >= mAnimatingAppTokens.size()) {
+            int i = NW;
+            while (i > 0) {
+                i--;
+                WindowState win = windows.get(i);
+                if (win.getAppToken() != null) {
+                    return i+1;
+                }
             }
         }
 
-        while (iterator.hasNext()) {
+        while (tokenPos > 0) {
             // 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);
+            final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
+            if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
+                    + tokenPos + " -- " + wtoken.token);
             if (wtoken.sendingToBottom) {
-                if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
+                if (DEBUG_REORDER) Slog.v(TAG,
+                        "Skipping token -- currently sending to bottom");
+                tokenPos--;
                 continue;
             }
-            for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
+            int i = wtoken.windows.size();
+            while (i > 0) {
+                i--;
                 WindowState win = wtoken.windows.get(i);
-                for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
+                int j = win.mChildWindows.size();
+                while (j > 0) {
+                    j--;
                     WindowState cwin = win.mChildWindows.get(j);
                     if (cwin.mSubLayer >= 0) {
-                        for (int pos = NW - 1; pos >= 0; pos--) {
+                        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;
+                                        "Found child win @" + (pos+1));
+                                return pos+1;
                             }
                         }
                     }
                 }
-                for (int pos = NW - 1; pos >= 0; pos--) {
+                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;
+                        if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
+                        return pos+1;
                     }
                 }
             }
+            tokenPos--;
         }
 
         return 0;
@@ -4499,104 +4505,198 @@
         return index;
     }
 
-    private void moveTaskWindowsLocked(int taskId) {
-        DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
-        if (displayContent == null) {
-            Slog.w(TAG, "moveTaskWindowsLocked: can't find DisplayContent for taskId=" + taskId);
-            return;
+    @Override
+    public void moveAppToken(int index, IBinder token) {
+        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+                "moveAppToken()")) {
+            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
-        TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
-        if (taskList == null) {
-            Slog.w(TAG, "moveTaskWindowsLocked: can't find TaskList for taskId=" + taskId);
-            return;
-        }
+        synchronized(mWindowMap) {
+            if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
+            if (DEBUG_REORDER) dumpAppTokensLocked();
+            final AppWindowToken wtoken = findAppWindowToken(token);
+            final int oldIndex = mAppTokens.indexOf(wtoken);
+            if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+                    "Start moving token " + wtoken + " initially at "
+                    + oldIndex);
+            if (oldIndex > index && mAppTransition.isTransitionSet()) {
+                // animation towards back has not started, copy old list for duration of animation.
+                mAnimatingAppTokens.clear();
+                mAnimatingAppTokens.addAll(mAppTokens);
+            }
+            if (wtoken == null || !mAppTokens.remove(wtoken)) {
+                Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
+                      + token + " (" + wtoken + ")");
+                return;
+            }
+            mAppTokens.add(index, wtoken);
+            if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
+            else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index);
+            if (DEBUG_REORDER) dumpAppTokensLocked();
+            if (!mAppTransition.isTransitionSet()) {
+                // Not animating, bring animating app list in line with mAppTokens.
+                mAnimatingAppTokens.clear();
+                mAnimatingAppTokens.addAll(mAppTokens);
 
+                // Bring window ordering, window focus and input window in line with new app token
+                final long origId = Binder.clearCallingIdentity();
+                if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
+                if (DEBUG_REORDER) dumpWindowsLocked();
+                if (tmpRemoveAppWindowsLocked(wtoken)) {
+                    if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
+                    if (DEBUG_REORDER) dumpWindowsLocked();
+                    DisplayContentsIterator iterator = new DisplayContentsIterator();
+                    while(iterator.hasNext()) {
+                        final DisplayContent displayContent = iterator.next();
+                        final WindowList windows = displayContent.getWindowList();
+                        final int pos = findWindowOffsetLocked(windows, index);
+                        final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
+                        if (pos != newPos) {
+                            displayContent.layoutNeeded = true;
+                        }
+                    }
+                    if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
+                    if (DEBUG_REORDER) dumpWindowsLocked();
+                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                            false /*updateInputWindows*/);
+                    mInputMonitor.setUpdateInputWindowsNeededLw();
+                    performLayoutAndPlaceSurfacesLocked();
+                    mInputMonitor.updateInputWindowsLw(false /*force*/);
+                }
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
+    private void removeAppTokensLocked(List<IBinder> tokens) {
+        // XXX This should be done more efficiently!
+        // (take advantage of the fact that both lists should be
+        // ordered in the same way.)
+        int N = tokens.size();
+        for (int i=0; i<N; i++) {
+            IBinder token = tokens.get(i);
+            final AppWindowToken wtoken = findAppWindowToken(token);
+            if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                    "Temporarily removing " + wtoken + " from " + mAppTokens.indexOf(wtoken));
+            if (!mAppTokens.remove(wtoken)) {
+                Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
+                      + token + " (" + wtoken + ")");
+                i--;
+                N--;
+            }
+        }
+    }
+
+    private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
         // First remove all of the windows from the list.
-        for (AppWindowToken wtoken : taskList.mAppTokens) {
-            tmpRemoveAppWindowsLocked(wtoken);
+        final int N = tokens.size();
+        int i;
+        for (i=0; i<N; i++) {
+            WindowToken token = mTokenMap.get(tokens.get(i));
+            if (token != null) {
+                tmpRemoveAppWindowsLocked(token);
+            }
         }
 
         // And now add them back at the correct place.
-        // Where to start adding?
-        int pos = findAppWindowInsertionPointLocked(taskList.mAppTokens.get(0));
-        for (AppWindowToken wtoken : taskList.mAppTokens) {
-            if (wtoken != null) {
-                final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
-                if (newPos != pos) {
-                    displayContent.layoutNeeded = true;
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
+        while (iterator.hasNext()) {
+            final DisplayContent displayContent = iterator.next();
+            final WindowList windows = displayContent.getWindowList();
+            // Where to start adding?
+            int pos = findWindowOffsetLocked(windows, tokenPos);
+            for (i=0; i<N; i++) {
+                WindowToken token = mTokenMap.get(tokens.get(i));
+                if (token != null) {
+                    final int newPos = reAddAppWindowsLocked(displayContent, pos, token);
+                    if (newPos != pos) {
+                        displayContent.layoutNeeded = true;
+                    }
+                    pos = newPos;
                 }
-                pos = newPos;
+            }
+            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/)) {
+                assignLayersLocked(windows);
             }
         }
-        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-            false /*updateInputWindows*/)) {
-            assignLayersLocked(displayContent.getWindowList());
-        }
 
-        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                false /*updateInputWindows*/);
         mInputMonitor.setUpdateInputWindowsNeededLw();
+
+        // Note that the above updateFocusedWindowLocked used to sit here.
+
         performLayoutAndPlaceSurfacesLocked();
         mInputMonitor.updateInputWindowsLw(false /*force*/);
 
         //dump();
     }
 
-    public void moveTaskToTop(int taskId) {
-        final long origId = Binder.clearCallingIdentity();
-        try {
-            synchronized(mWindowMap) {
-                DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
-                if (displayContent == null) {
-                    Slog.e(TAG, "moveTaskToTop: taskId=" + taskId
-                            + " not found in mTaskIdToDisplayContents");
-                    return;
-                }
-                TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
-                if (taskList == null) {
-                    Slog.e(TAG, "moveTaskToTop: taskId=" + taskId
-                            + " not found in mTaskIdToTaskLists");
-                    return;
-                }
-                if (!displayContent.mTaskLists.remove(taskList)) {
-                    Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskLists");
-                }
-                displayContent.mTaskLists.add(taskList);
-
-                moveTaskWindowsLocked(taskId);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(origId);
+    @Override
+    public void moveAppTokensToTop(List<IBinder> tokens) {
+        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+                "moveAppTokensToTop()")) {
+            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
+
+        final long origId = Binder.clearCallingIdentity();
+        synchronized(mWindowMap) {
+            removeAppTokensLocked(tokens);
+            final int N = tokens.size();
+            for (int i=0; i<N; i++) {
+                AppWindowToken wt = findAppWindowToken(tokens.get(i));
+                if (wt != null) {
+                    if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+                            "Adding next to top: " + wt);
+                    mAppTokens.add(wt);
+                    if (mAppTransition.isTransitionSet()) {
+                        wt.sendingToBottom = false;
+                    }
+                }
+            }
+
+            mAnimatingAppTokens.clear();
+            mAnimatingAppTokens.addAll(mAppTokens);
+            moveAppWindowsLocked(tokens, mAppTokens.size());
+        }
+        Binder.restoreCallingIdentity(origId);
     }
 
-    public void moveTaskToBottom(int taskId) {
-        final long origId = Binder.clearCallingIdentity();
-        try {
-            synchronized(mWindowMap) {
-                DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
-                if (displayContent == null) {
-                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
-                            + " not found in mTaskIdToDisplayContents");
-                    return;
-                }
-                TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
-                if (taskList == null) {
-                    Slog.e(TAG, "moveTaskToTopBottom: taskId=" + taskId
-                            + " not found in mTaskIdToTaskLists");
-                    return;
-                }
-                if (!displayContent.mTaskLists.remove(taskList)) {
-                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId + " not found in mTaskLists");
-                }
-                displayContent.mTaskLists.add(0, taskList);
-
-                moveTaskWindowsLocked(taskId);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(origId);
+    @Override
+    public void moveAppTokensToBottom(List<IBinder> tokens) {
+        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+                "moveAppTokensToBottom()")) {
+            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
+
+        final long origId = Binder.clearCallingIdentity();
+        synchronized(mWindowMap) {
+            final int N = tokens.size();
+            if (N > 0) {
+                // animating towards back, hang onto old list for duration of animation.
+                mAnimatingAppTokens.clear();
+                mAnimatingAppTokens.addAll(mAppTokens);
+            }
+            removeAppTokensLocked(tokens);
+            int pos = 0;
+            for (int i=0; i<N; i++) {
+                AppWindowToken wt = findAppWindowToken(tokens.get(i));
+                if (wt != null) {
+                    if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                            "Adding next to bottom: " + wt + " at " + pos);
+                    mAppTokens.add(pos, wt);
+                    if (mAppTransition.isTransitionSet()) {
+                        wt.sendingToBottom = true;
+                    }
+                    pos++;
+                }
+            }
+
+            mAnimatingAppTokens.clear();
+            mAnimatingAppTokens.addAll(mAppTokens);
+            moveAppWindowsLocked(tokens, 0);
+        }
+        Binder.restoreCallingIdentity(origId);
     }
 
     // -------------------------------------------------------------
@@ -4717,9 +4817,9 @@
     @Override
     public void closeSystemDialogs(String reason) {
         synchronized(mWindowMap) {
-            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
-            while (mTmpWindowsIterator.hasNext()) {
-                final WindowState w = mTmpWindowsIterator.next();
+            final AllWindowsIterator iterator = new AllWindowsIterator();
+            while (iterator.hasNext()) {
+                final WindowState w = iterator.next();
                 if (w.mHasSurface) {
                     try {
                         w.mClient.closeSystemDialogs(reason);
@@ -5113,9 +5213,9 @@
             // the background..)
             if (on) {
                 boolean isVisible = false;
-                mTmpWindowsIterator.reset(FORWARD_ITERATOR);
-                while (mTmpWindowsIterator.hasNext()) {
-                    final WindowState ws = mTmpWindowsIterator.next();
+                final AllWindowsIterator iterator = new AllWindowsIterator();
+                while (iterator.hasNext()) {
+                    final WindowState ws = iterator.next();
                     if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
                         isVisible = true;
                         break;
@@ -6010,9 +6110,9 @@
         }
 
         synchronized (mWindowMap) {
-            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
-            while (mTmpWindowsIterator.hasNext()) {
-                final WindowState w = mTmpWindowsIterator.next();
+            final AllWindowsIterator iterator = new AllWindowsIterator();
+            while (iterator.hasNext()) {
+                final WindowState w = iterator.next();
                 if (System.identityHashCode(w) == hashCode) {
                     return w;
                 }
@@ -6561,10 +6661,10 @@
     // TODO(multidisplay): Call isScreenOn for each display.
     private void sendScreenStatusToClientsLocked() {
         final boolean on = mPowerManager.isScreenOn();
-        mTmpWindowsIterator.reset(FORWARD_ITERATOR);
-        while (mTmpWindowsIterator.hasNext()) {
+        final AllWindowsIterator iterator = new AllWindowsIterator();
+        while (iterator.hasNext()) {
             try {
-                mTmpWindowsIterator.next().mClient.dispatchScreenState(on);
+                iterator.next().mClient.dispatchScreenState(on);
             } catch (RemoteException e) {
                 // Ignored
             }
@@ -6860,6 +6960,8 @@
                         if (mAppTransition.isTransitionSet()) {
                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
                             mAppTransition.setTimeout();
+                            mAnimatingAppTokens.clear();
+                            mAnimatingAppTokens.addAll(mAppTokens);
                             performLayoutAndPlaceSurfacesLocked();
                         }
                     }
@@ -6904,11 +7006,10 @@
                 case APP_FREEZE_TIMEOUT: {
                     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();
+                        int i = mAppTokens.size();
+                        while (i > 0) {
+                            i--;
+                            AppWindowToken tok = mAppTokens.get(i);
                             if (tok.mAppAnimator.freezingScreen) {
                                 Slog.w(TAG, "Force clearing freeze: " + tok);
                                 unsetAppFreezingScreenLocked(tok, true, true);
@@ -7307,7 +7408,6 @@
         performLayoutAndPlaceSurfacesLocked();
     }
 
-    @Override
     public void setOverscan(int displayId, int left, int top, int right, int bottom) {
         if (mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
@@ -7426,16 +7526,15 @@
         // in the main app list, but still have windows shown.  We put them
         // in the back because now that the animation is over we no longer
         // will care about them.
-        AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
-        int NT = exitingAppTokens.size();
+        int NT = mExitingAppTokens.size();
         for (int j=0; j<NT; j++) {
-            i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
+            i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j));
         }
 
         // 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());
+        NT = mAnimatingAppTokens.size();
+        for (int j=0; j<NT; j++) {
+            i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j));
         }
 
         i -= lastBelow;
@@ -7455,7 +7554,7 @@
                 }
             }
             Slog.w(TAG, "Current app token list:");
-            dumpAppTokensLocked();
+            dumpAnimatingAppTokensLocked();
             Slog.w(TAG, "Final window list:");
             dumpWindowsLocked();
         }
@@ -8105,11 +8204,11 @@
 
         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;
+        for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) {
+            mAnimatingAppTokens.get(i).sendingToBottom = false;
         }
+        mAnimatingAppTokens.clear();
+        mAnimatingAppTokens.addAll(mAppTokens);
         rebuildAppWindowListLocked();
 
         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
@@ -8266,12 +8365,13 @@
         }
     }
 
-    private void updateAllDrawnLocked(DisplayContent displayContent) {
+    private void updateAllDrawnLocked() {
         // 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();
+        final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens;
+        final int NT = appTokens.size();
+        for (int i=0; i<NT; i++) {
+            AppWindowToken wtoken = appTokens.get(i);
             if (!wtoken.allDrawn) {
                 int numInteresting = wtoken.numInterestingWindows;
                 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
@@ -8303,17 +8403,13 @@
         }
 
         // Initialize state of exiting tokens.
-        DisplayContentsIterator iterator = new DisplayContentsIterator();
-        while (iterator.hasNext()) {
-            final DisplayContent displayContent = iterator.next();
-            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
-                displayContent.mExitingTokens.get(i).hasVisible = false;
-            }
+        for (i=mExitingTokens.size()-1; i>=0; i--) {
+            mExitingTokens.get(i).hasVisible = false;
+        }
 
-            // Initialize state of exiting applications.
-            for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
-                displayContent.mExitingAppTokens.get(i).hasVisible = false;
-            }
+        // Initialize state of exiting applications.
+        for (i=mExitingAppTokens.size()-1; i>=0; i--) {
+            mExitingAppTokens.get(i).hasVisible = false;
         }
 
         mInnerFields.mHoldScreen = null;
@@ -8342,10 +8438,10 @@
             }
 
             boolean focusDisplayed = false;
+            boolean updateAllDrawn = false;
 
-            iterator = new DisplayContentsIterator();
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
             while (iterator.hasNext()) {
-                boolean updateAllDrawn = false;
                 final DisplayContent displayContent = iterator.next();
                 WindowList windows = displayContent.getWindowList();
                 DisplayInfo displayInfo = displayContent.getDisplayInfo();
@@ -8589,10 +8685,10 @@
                 if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
                     stopDimmingLocked(displayId);
                 }
+            }
 
-                if (updateAllDrawn) {
-                    updateAllDrawnLocked(displayContent);
-                }
+            if (updateAllDrawn) {
+                updateAllDrawnLocked();
             }
 
             if (focusDisplayed) {
@@ -8739,35 +8835,30 @@
         }
 
         // Time to remove any exiting tokens?
-        iterator = new DisplayContentsIterator();
-        while (iterator.hasNext()) {
-            final DisplayContent displayContent = iterator.next();
-            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
-            for (i = exitingTokens.size() - 1; i >= 0; i--) {
-                WindowToken token = exitingTokens.get(i);
-                if (!token.hasVisible) {
-                    exitingTokens.remove(i);
-                    if (token.windowType == TYPE_WALLPAPER) {
-                        mWallpaperTokens.remove(token);
-                    }
+        for (i=mExitingTokens.size()-1; i>=0; i--) {
+            WindowToken token = mExitingTokens.get(i);
+            if (!token.hasVisible) {
+                mExitingTokens.remove(i);
+                if (token.windowType == TYPE_WALLPAPER) {
+                    mWallpaperTokens.remove(token);
                 }
             }
+        }
 
-            // Time to remove any exiting applications?
-            AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
-            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
-                AppWindowToken token = exitingAppTokens.get(i);
-                if (!token.hasVisible && !mClosingApps.contains(token)) {
-                    // Make sure there is no animation running on this token,
-                    // so any windows associated with it will be removed as
-                    // soon as their animations are complete
-                    token.mAppAnimator.clearAnimation();
-                    token.mAppAnimator.animating = false;
-                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
-                            "performLayout: App token exiting now removed" + token);
-                    displayContent.removeAppToken(token);
-                    exitingAppTokens.remove(i);
-                }
+        // Time to remove any exiting applications?
+        for (i=mExitingAppTokens.size()-1; i>=0; i--) {
+            AppWindowToken token = mExitingAppTokens.get(i);
+            if (!token.hasVisible && !mClosingApps.contains(token)) {
+                // Make sure there is no animation running on this token,
+                // so any windows associated with it will be removed as
+                // soon as their animations are complete
+                token.mAppAnimator.clearAnimation();
+                token.mAppAnimator.animating = false;
+                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                        "performLayout: App token exiting now removed" + token);
+                mAppTokens.remove(token);
+                mAnimatingAppTokens.remove(token);
+                mExitingAppTokens.remove(i);
             }
         }
 
@@ -8787,7 +8878,7 @@
             defaultDisplay.layoutNeeded = true;
         }
 
-        iterator = new DisplayContentsIterator();
+        DisplayContentsIterator iterator = new DisplayContentsIterator();
         while (iterator.hasNext()) {
             DisplayContent displayContent = iterator.next();
             if (displayContent.pendingLayoutChanges != 0) {
@@ -9038,10 +9129,10 @@
             // window list to make sure we haven't left any dangling surfaces
             // around.
 
-            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+            AllWindowsIterator iterator = new AllWindowsIterator();
             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
-            while (mTmpWindowsIterator.hasNext()) {
-                WindowState ws = mTmpWindowsIterator.next();
+            while (iterator.hasNext()) {
+                WindowState ws = iterator.next();
                 WindowStateAnimator wsa = ws.mWinAnimator;
                 if (wsa.mSurfaceControl != null) {
                     if (!mSessions.contains(wsa.mSession)) {
@@ -9074,9 +9165,9 @@
             if (!leakedSurface) {
                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
                 SparseIntArray pidCandidates = new SparseIntArray();
-                mTmpWindowsIterator.reset(FORWARD_ITERATOR);
-                while (mTmpWindowsIterator.hasNext()) {
-                    WindowState ws = mTmpWindowsIterator.next();
+                iterator = new AllWindowsIterator();
+                while (iterator.hasNext()) {
+                    WindowState ws = iterator.next();
                     if (mForceRemoves.contains(ws)) {
                         continue;
                     }
@@ -9202,8 +9293,8 @@
     }
 
     private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
-        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
-        WindowToken nextApp = iterator.hasNext() ? iterator.next() : null;
+        int nextAppIndex = mAppTokens.size()-1;
+        WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null;
 
         final WindowList windows = displayContent.getWindowList();
         for (int i = windows.size() - 1; i >= 0; i--) {
@@ -9229,8 +9320,8 @@
             // through the app tokens until we find its app.
             if (thisApp != null && nextApp != null && thisApp != nextApp
                     && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
-                final WindowToken origAppToken = nextApp;
-                while (iterator.hasNext()) {
+                int origAppIndex = nextAppIndex;
+                while (nextAppIndex > 0) {
                     if (nextApp == mFocusedApp) {
                         // Whoops, we are below the focused app...  no focus
                         // for you!
@@ -9238,7 +9329,8 @@
                             TAG, "Reached focused app: " + mFocusedApp);
                         return null;
                     }
-                    nextApp = iterator.next();
+                    nextAppIndex--;
+                    nextApp = mAppTokens.get(nextAppIndex);
                     if (nextApp == thisApp) {
                         break;
                     }
@@ -9247,14 +9339,8 @@
                     // Uh oh, the app token doesn't exist!  This shouldn't
                     // 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;
-                        }
-                    } 
+                    nextAppIndex = origAppIndex;
+                    nextApp = mAppTokens.get(nextAppIndex);
                 }
             }
 
@@ -9624,6 +9710,15 @@
                 }
             }
         }
+        if (mAppTokens.size() > 0) {
+            pw.println();
+            pw.println("  Application tokens in Z order:");
+            for (int i=mAppTokens.size()-1; i>=0; i--) {
+                pw.print("  App #"); pw.print(i);
+                        pw.print(' '); pw.print(mAppTokens.get(i)); pw.println(":");
+                mAppTokens.get(i).dump(pw, "    ");
+            }
+        }
         if (mFinishedStarting.size() > 0) {
             pw.println();
             pw.println("  Finishing start of application tokens:");
@@ -9639,6 +9734,51 @@
                 }
             }
         }
+        if (mExitingTokens.size() > 0) {
+            pw.println();
+            pw.println("  Exiting tokens:");
+            for (int i=mExitingTokens.size()-1; i>=0; i--) {
+                WindowToken token = mExitingTokens.get(i);
+                pw.print("  Exiting #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        if (mExitingAppTokens.size() > 0) {
+            pw.println();
+            pw.println("  Exiting application tokens:");
+            for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
+                WindowToken token = mExitingAppTokens.get(i);
+                pw.print("  Exiting App #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        if (mAppTransition.isRunning() && mAnimatingAppTokens.size() > 0) {
+            pw.println();
+            pw.println("  Application tokens during animation:");
+            for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) {
+                WindowToken token = mAnimatingAppTokens.get(i);
+                pw.print("  App moving to bottom #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
         if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
             pw.println();
             if (mOpeningApps.size() > 0) {
@@ -9683,9 +9823,9 @@
     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
         int j = 0;
-        mTmpWindowsIterator.reset(REVERSE_ITERATOR);
-        while (mTmpWindowsIterator.hasNext()) {
-            final WindowState w = mTmpWindowsIterator.next();
+        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+        while (iterator.hasNext()) {
+            final WindowState w = iterator.next();
             if (windows == null || windows.contains(w)) {
                 pw.print("  Window #"); pw.print(j++); pw.print(' ');
                         pw.print(w); pw.println(":");
@@ -9871,9 +10011,9 @@
         WindowList windows = new WindowList();
         if ("visible".equals(name)) {
             synchronized(mWindowMap) {
-                mTmpWindowsIterator.reset(REVERSE_ITERATOR);
-                while (mTmpWindowsIterator.hasNext()) {
-                    final WindowState w = mTmpWindowsIterator.next();
+                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+                while (iterator.hasNext()) {
+                    final WindowState w = iterator.next();
                     if (w.mWinAnimator.mSurfaceShown) {
                         windows.add(w);
                     }
@@ -9888,9 +10028,9 @@
             } catch (RuntimeException e) {
             }
             synchronized(mWindowMap) {
-                mTmpWindowsIterator.reset(REVERSE_ITERATOR);
-                while (mTmpWindowsIterator.hasNext()) {
-                    final WindowState w = mTmpWindowsIterator.next();
+                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+                while (iterator.hasNext()) {
+                    final WindowState w = iterator.next();
                     if (name != null) {
                         if (w.mAttrs.getTitle().toString().contains(name)) {
                             windows.add(w);
@@ -10143,10 +10283,6 @@
     class DisplayContentsIterator implements Iterator<DisplayContent> {
         private int cur;
 
-        void reset() {
-            cur = 0;
-        }
-
         @Override
         public boolean hasNext() {
             return cur < mDisplayContents.size();
@@ -10166,6 +10302,7 @@
         }
     }
 
+    final static boolean REVERSE_ITERATOR = true;
     class AllWindowsIterator implements Iterator<WindowState> {
         private DisplayContent mDisplayContent;
         private DisplayContentsIterator mDisplayContentsIterator;
@@ -10174,33 +10311,19 @@
         private boolean mReverse;
 
         AllWindowsIterator() {
-            this(false);
+            mDisplayContentsIterator = new DisplayContentsIterator();
+            mDisplayContent = mDisplayContentsIterator.next();
+            mWindowList = mDisplayContent.getWindowList();
         }
 
         AllWindowsIterator(boolean reverse) {
-            mDisplayContentsIterator = new DisplayContentsIterator();
-            reset(reverse);
-        }
-
-        void reset(boolean reverse) {
+            this();
             mReverse = reverse;
-            mDisplayContentsIterator.reset();
-            if (mDisplayContentsIterator.hasNext()) {
-                mDisplayContent = mDisplayContentsIterator.next();
-                mWindowList = mDisplayContent.getWindowList();
-                mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
-            } else {
-                mDisplayContent = null;
-                mWindowList = null;
-                mWindowListIndex = 0;
-            }
+            mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
         }
 
         @Override
         public boolean hasNext() {
-            if (mDisplayContent == null) {
-                return false;
-            }
             if (mReverse) {
                 return mWindowListIndex >= 0;
             }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 517c4e4..a600623 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -52,12 +52,6 @@
 import java.util.ArrayList;
 
 class WindowList extends ArrayList<WindowState> {
-    WindowList() {
-        super();
-    }
-    WindowList(WindowList windows) {
-        super(windows);
-    }
 }
 
 /**
@@ -1092,7 +1086,7 @@
         return true;
     }
 
-    public void setAppOpVisibilityLw(boolean state) {
+    public boolean setAppOpVisibilityLw(boolean state) {
         if (mAppOpVisibility != state) {
             mAppOpVisibility = state;
             if (state) {
@@ -1102,11 +1096,13 @@
                 // ops modifies they should only be hidden by policy due to the
                 // lock screen, and the user won't be changing this if locked.
                 // Plus it will quickly be fixed the next time we do a layout.
-                showLw(true, true);
+                showLw(true, false);
             } else {
-                hideLw(true, true);
+                hideLw(true, false);
             }
+            return true;
         }
+        return false;
     }
 
     @Override
diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/java/com/android/server/wm/WindowToken.java
index 2267123..bd0ace8 100644
--- a/services/java/com/android/server/wm/WindowToken.java
+++ b/services/java/com/android/server/wm/WindowToken.java
@@ -19,6 +19,7 @@
 import android.os.IBinder;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
 /**
  * Container of a set of related windows in the window manager.  Often this