Switch topRunning* and moveTaskTo*

- More of the Activity to Task changeover.
- Fix bug in validateAppTokens().
- Improved validation of changeover.
- Eliminated iterator classes.

Change-Id: I934a208eabfc9a2668e5a6162452e1406f2c8d3a
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index a18a0d1..30a7e23 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -77,7 +77,6 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.NoSuchElementException;
 
 /**
  * State and management of a single stack of activities.
@@ -142,9 +141,6 @@
     // is being started.
     static final boolean SHOW_APP_STARTING_PREVIEW = true;
 
-    static final boolean FORWARD_ITERATOR = false;
-    static final boolean REVERSE_ITERATOR = true;
-
     enum ActivityState {
         INITIALIZING,
         RESUMED,
@@ -307,12 +303,6 @@
      */
     boolean mDismissKeyguardOnNextActivity = false;
 
-    /** So we don't have to keep constructing a new object for utility non-nested use. */
-    final ActivityIterator mTmpActivityIterator = new ActivityIterator(FORWARD_ITERATOR, true);
-
-    /** So we don't have to keep constructing a new object for utility non-nested use. */
-    final TaskIterator mTmpTaskIterator = new TaskIterator();
-
     /**
      * Save the most recent screenshot for reuse. This keeps Recents from taking two identical
      * screenshots, one for the Recents thumbnail and one for the pauseActivity thumbnail.
@@ -355,6 +345,8 @@
 
     final Handler mHandler;
 
+    String mLastHistoryModifier;
+
     final class ActivityStackHandler extends Handler {
         //public Handler() {
         //    if (localLOGV) Slog.v(TAG, "Handler started!");
@@ -481,26 +473,66 @@
     }
 
     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;
     }
 
@@ -514,16 +546,40 @@
      * @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;
     }
 
@@ -1002,7 +1058,7 @@
         }
         // Ensure activities are no longer sleeping.
         if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords();
+            verifyActivityRecords(true);
         }
         for (int i=mHistory.size()-1; i>=0; i--) {
             ActivityRecord r = mHistory.get(i);
@@ -1049,7 +1105,7 @@
             // Make sure any stopped but visible activities are now sleeping.
             // This ensures that the activity's onStop() is called.
             if (VALIDATE_TASK_REPLACE) {
-                verifyActivityRecords();
+                verifyActivityRecords(true);
             }
             for (int i=mHistory.size()-1; i>=0; i--) {
                 ActivityRecord r = mHistory.get(i);
@@ -1196,7 +1252,7 @@
 
         synchronized (mService) {
             if (VALIDATE_TASK_REPLACE) {
-                verifyActivityRecords();
+                verifyActivityRecords(true);
             }
             int index = indexOfTokenLocked(token);
             if (index >= 0) {
@@ -1216,7 +1272,7 @@
 
         synchronized (mService) {
             if (VALIDATE_TASK_REPLACE) {
-                verifyActivityRecords();
+                verifyActivityRecords(true);
             }
             int index = indexOfTokenLocked(token);
             if (index >= 0) {
@@ -1431,7 +1487,7 @@
         // 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();
+            verifyActivityRecords(true);
         }
         final int count = mHistory.size();
         int i = count-1;
@@ -1969,8 +2025,21 @@
         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;
@@ -1998,11 +2067,12 @@
                         r.task.addActivityToTop(r);
                         mHistory.add(addPos, r);
                         r.putInHistory();
-                        mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
-                                r.info.screenOrientation, r.fullscreen,
+                        mService.mWindowManager.addAppToken(convertAddPos(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;
@@ -2039,6 +2109,11 @@
         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
@@ -2064,8 +2139,8 @@
                 mNoAnimActivities.remove(r);
             }
             r.updateOptionsLocked(options);
-            mService.mWindowManager.addAppToken(
-                    addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
+            mService.mWindowManager.addAppToken(convertAddPos(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) {
@@ -2103,7 +2178,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(addPos, r.appToken, r.task.taskId,
+            mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken, r.task.taskId,
                     r.info.screenOrientation, r.fullscreen,
                     (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
             ActivityOptions.abort(options);
@@ -2116,7 +2191,9 @@
             resumeTopActivityLocked(null);
         }
         if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords();
+            if (verifyActivityRecords(true)) {
+                Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
+            }
         }
     }
 
@@ -2144,6 +2221,8 @@
      */
     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
@@ -2281,6 +2360,7 @@
                             dstPos++;
                             i++;
                         }
+                        rebuildTaskHistory();
                         mService.mWindowManager.moveTaskToBottom(taskId);
                         if (VALIDATE_TOKENS) {
                             validateAppTokensLocked();
@@ -2429,6 +2509,7 @@
                                 + " 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) {
@@ -2478,7 +2559,7 @@
         }
 
         if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords();
+            verifyActivityRecords(true);
         }
         return taskTop;
     }
@@ -2644,6 +2725,7 @@
      */
     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) {
@@ -2653,6 +2735,17 @@
                     + 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;
@@ -2663,6 +2756,7 @@
             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;
 
@@ -4294,8 +4388,9 @@
             here.fillInStackTrace();
             Slog.i(TAG, "Removing activity " + r + " from stack");
         }
-        if (r.task != null) {
-            r.task.removeActivity(r);
+        final TaskRecord task = r.task;
+        if (task != null) {
+            task.removeActivity(r);
         }
         mHistory.remove(r);
         r.takeFromHistory();
@@ -4597,6 +4692,7 @@
      * of the stack.
      */
     final void moveHomeToFrontLocked() {
+        newMoveHomeToFrontLocked();
         TaskRecord homeTask = null;
         for (int i=mHistory.size()-1; i>=0; i--) {
             ActivityRecord hr = mHistory.get(i);
@@ -4606,6 +4702,23 @@
             }
         }
         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);
         }
     }
@@ -4642,31 +4755,19 @@
     }
 
     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(
@@ -4680,18 +4781,37 @@
                 }
                 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);
 
-        if (DEBUG_TRANSITION) Slog.v(TAG,
-                "Prepare to front transition: task=" + 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 (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);
@@ -4702,12 +4822,16 @@
         }
 
         mService.mWindowManager.moveTaskToTop(task);
-        if (VALIDATE_TOKENS) {
-            validateAppTokensLocked();
-        }
 
         finishTaskMoveLocked(task);
         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
+
+        if (VALIDATE_TOKENS) {
+            validateAppTokensLocked();
+        }
+        if (VALIDATE_TASK_REPLACE) {
+            verifyActivityRecords(true);
+        }
     }
 
     private final void finishTaskMoveLocked(int task) {
@@ -4726,6 +4850,42 @@
      * @return Returns true if the move completed, false if not.
      */
     final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
+        if (!newMoveTaskToBackLocked(task, reason)) {
+            return false;
+        }
+
+        final int N = mHistory.size();
+        int bottom = 0;
+        int pos = 0;
+
+        // Shift all activities with this task down to the bottom
+        // of the stack, keeping them in the same internal order.
+        while (pos < N) {
+            ActivityRecord r = mHistory.get(pos);
+            if (localLOGV) Slog.v(
+                TAG, "At " + pos + " ckp " + r.task + ": " + r);
+            if (r.task.taskId == task) {
+                if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
+                if (DEBUG_ADD_REMOVE) {
+                    RuntimeException here = new RuntimeException("here");
+                    here.fillInStackTrace();
+                    Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
+                            + bottom, here);
+                }
+                mHistory.remove(pos);
+                mHistory.add(bottom, r);
+                bottom++;
+            }
+            pos++;
+        }
+        if (VALIDATE_TASK_REPLACE) {
+            verifyActivityRecords(true);
+        }
+
+        return true;
+    }
+
+    final boolean newMoveTaskToBackLocked(int task, ActivityRecord reason) {
         Slog.i(TAG, "moveTaskToBack: " + task);
         
         // If we have a watcher, preflight the move before committing to it.  First check
@@ -4750,41 +4910,16 @@
             }
         }
 
-        ArrayList<IBinder> moved = new ArrayList<IBinder>();
-
         if (DEBUG_TRANSITION) Slog.v(TAG,
                 "Prepare to back transition: task=" + task);
-        
-        final int N = mHistory.size();
-        int bottom = 0;
-        int pos = 0;
 
-        // Shift all activities with this task down to the bottom
-        // of the stack, keeping them in the same internal order.
-        while (pos < N) {
-            ActivityRecord r = mHistory.get(pos);
-            if (localLOGV) Slog.v(
-                TAG, "At " + pos + " ckp " + r.task + ": " + r);
-            if (r.task.taskId == task) {
-                if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
-                if (DEBUG_ADD_REMOVE) {
-                    RuntimeException here = new RuntimeException("here");
-                    here.fillInStackTrace();
-                    Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
-                            + bottom, here);
-                }
-                mHistory.remove(pos);
-                mHistory.add(bottom, r);
-                moved.add(r.appToken);
-                bottom++;
-            }
-            pos++;
-        }
+        final TaskRecord tr = mTaskIdToTaskRecord.get(task);
+        mTaskHistory.remove(tr);
+        mTaskHistory.add(0, 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);
@@ -5307,33 +5442,65 @@
         return starting;
     }
 
-    void verifyActivityRecords() {
-        /* Until we have activity movement implemented for tasks just do the simple test
-        ActivityIterator iterator = new ActivityIterator();
-        int i;
-        int N = mHistory.size();
-        for (i = 0; i < N && iterator.hasNext(); ++i) {
-            ActivityRecord r1 = mHistory.get(i);
-            ActivityRecord r2 = iterator.next();
-            if (r1 != r2) {
+    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 (i != N || iterator.hasNext()) {
-            Slog.w(TAG, "verifyActivityRecords mHistory=" + mHistory
-                + " mTaskHistory=" + iterator + " Callers=" + Debug.getCallers(2));
-        } */
-        // Simple test
-        ActivityIterator iterator = new ActivityIterator();
-        while (iterator.hasNext()) {
-            ActivityRecord r = iterator.next();
-            if (!mHistory.contains(r)) {
-                break;
-            }
+        if (taskNdx != numTasks || historyNdx != numHistory) {
+            logHistories("verifyActivityRecords", rebuild);
+            return true;
         }
-        if (iterator.size() != mHistory.size() || iterator.hasNext()) {
-            Slog.w(TAG, "verifyActivityRecords mHistory=" + mHistory
-                + " mTaskHistory=" + iterator + " Callers=" + Debug.getCallers(2));
+        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();
         }
     }
 
@@ -5353,138 +5520,4 @@
         }
         return task;
     }
-
-    class TaskIterator implements Iterator<TaskRecord> {
-        private int mCur;
-        private boolean mReverse;
-
-        TaskIterator() {
-            this(FORWARD_ITERATOR);
-        }
-
-        TaskIterator(boolean reverse) {
-            reset(reverse);
-        }
-
-        public void reset(boolean reverse) {
-            mReverse = reverse;
-            mCur = reverse ? mTaskHistory.size() - 1 : 0;
-        }
-
-        @Override
-        public boolean hasNext() {
-            if (mReverse) {
-                return mCur >= 0;
-            }
-            return mCur < mTaskHistory.size();
-        }
-
-        @Override
-        public TaskRecord next() {
-            if (hasNext()) {
-                TaskRecord task = mTaskHistory.get(mCur);
-                mCur += (mReverse ? -1 : 1);
-                return task;
-            }
-            throw new NoSuchElementException();
-        }
-
-        @Override
-        public void remove() {
-            throw new IllegalArgumentException();
-        }
-    }
-
-    class ActivityIterator implements Iterator<ActivityRecord> {
-        final TaskIterator mIterator;
-        boolean mReverse;
-        int mCur;
-        TaskRecord mTaskRecord;
-        final boolean mSkipFinishing;
-
-        public ActivityIterator() {
-            this(FORWARD_ITERATOR);
-        }
-
-        public ActivityIterator(boolean reverse) {
-            this(reverse, false);
-        }
-
-        public ActivityIterator(boolean reverse, boolean skipFinishing) {
-            mSkipFinishing = skipFinishing;
-            mIterator = new TaskIterator();
-            reset(reverse);
-        }
-
-        public void reset(boolean reverse) {
-            mReverse = reverse;
-            mIterator.reset(reverse);
-            getNextTaskRecord();
-        }
-
-        private void getNextTaskRecord() {
-            if (mIterator.hasNext()) {
-                mTaskRecord = mIterator.next();
-                mCur = mReverse ? mTaskRecord.mActivities.size() - 1 : 0;
-            }
-        }
-
-        @Override
-        public boolean hasNext() {
-            if (mTaskRecord == null) {
-                return false;
-            }
-            if (mReverse) {
-                return mCur >= 0;
-            }
-            return mCur < mTaskRecord.mActivities.size();
-        }
-
-        @Override
-        public ActivityRecord next() {
-            while (hasNext()) {
-                ActivityRecord r = mTaskRecord.mActivities.get(mCur);
-                mCur += mReverse ? -1 : 1;
-                if (!hasNext()) {
-                    getNextTaskRecord();
-                }
-                if (mSkipFinishing && r.finishing) {
-                    continue;
-                }
-                return r;
-            }
-            throw new NoSuchElementException();
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        int size() {
-            int size = 0;
-            final TaskIterator iterator = new TaskIterator();
-            while (iterator.hasNext()) {
-                size += iterator.next().mActivities.size();
-            }
-            return size;
-        }
-
-        ActivityRecord peek() {
-            if (mTaskRecord != null && mCur >= 0 && mCur < mTaskRecord.mActivities.size()) {
-                return mTaskRecord.mActivities.get(mCur);
-            }
-            return null;
-        }
-
-        @Override
-        public String toString() {
-            StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < mTaskHistory.size(); ++i) {
-                final TaskRecord task = mTaskHistory.get(i);
-                sb.append("task_").append(i).append("-").append(task.mActivities).append(" ");
-            }
-            return sb.toString();
-        }
-    }
 }