OSDN Git Service

Revert ActivityManager changes for tasks. DO NOT MERGE
authorCraig Mautner <cmautner@google.com>
Tue, 26 Feb 2013 00:19:24 +0000 (16:19 -0800)
committerCraig Mautner <cmautner@google.com>
Tue, 26 Feb 2013 01:07:39 +0000 (17:07 -0800)
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

17 files changed:
core/java/android/view/IWindowManager.aidl
services/java/com/android/server/am/ActivityManagerService.java
services/java/com/android/server/am/ActivityRecord.java
services/java/com/android/server/am/ActivityStack.java
services/java/com/android/server/am/CompatModePackages.java
services/java/com/android/server/am/PendingThumbnailsRecord.java
services/java/com/android/server/am/TaskRecord.java
services/java/com/android/server/wm/AppWindowToken.java
services/java/com/android/server/wm/DisplayContent.java
services/java/com/android/server/wm/TaskGroup.java [deleted file]
services/java/com/android/server/wm/TaskList.java [deleted file]
services/java/com/android/server/wm/WindowAnimator.java
services/java/com/android/server/wm/WindowManagerService.java
services/java/com/android/server/wm/WindowState.java
services/java/com/android/server/wm/WindowToken.java
tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java

index e4ecb5c..f0c6241 100644 (file)
@@ -99,6 +99,9 @@ interface IWindowManager
     void startAppFreezingScreen(IBinder token, int configChanges);
     void stopAppFreezingScreen(IBinder token, boolean force);
     void removeAppToken(IBinder token);
+    void moveAppToken(int index, IBinder token);
+    void moveAppTokensToTop(in List<IBinder> tokens);
+    void moveAppTokensToBottom(in List<IBinder> tokens);
 
     // Re-evaluate the current orientation from the caller's state.
     // If there is a change, the new Configuration is returned and the
index 22af3d5..f226683 100644 (file)
@@ -37,7 +37,6 @@ import dalvik.system.Zygote;
 
 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 @@ public final class ActivityManagerService  extends ActivityManagerNative
     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 @@ public final class ActivityManagerService  extends ActivityManagerNative
     /**
      * 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 @@ public final class ActivityManagerService  extends ActivityManagerNative
      * 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 @@ public final class ActivityManagerService  extends ActivityManagerNative
             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 @@ public final class ActivityManagerService  extends ActivityManagerNative
         }
     }
 
-    @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 @@ public final class ActivityManagerService  extends ActivityManagerNative
         }
         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 @@ public final class ActivityManagerService  extends ActivityManagerNative
         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 @@ public final class ActivityManagerService  extends ActivityManagerNative
     // 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 @@ public final class ActivityManagerService  extends ActivityManagerNative
                 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;
+
+                // 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.pendingRecords.isEmpty()) {
+            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 @@ public final class ActivityManagerService  extends ActivityManagerNative
         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 @@ public final class ActivityManagerService  extends ActivityManagerNative
                     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 @@ public final class ActivityManagerService  extends ActivityManagerNative
         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,8 +6165,25 @@ public final class ActivityManagerService  extends ActivityManagerNative
 
     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;
     }
 
     // =========================================================
@@ -6909,10 +7091,13 @@ public final class ActivityManagerService  extends ActivityManagerNative
                 "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 @@ public final class ActivityManagerService  extends ActivityManagerNative
                     + " 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 @@ public final class ActivityManagerService  extends ActivityManagerNative
             }
             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 @@ public final class ActivityManagerService  extends ActivityManagerNative
             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 @@ public final class ActivityManagerService  extends ActivityManagerNative
      */
     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 @@ public final class ActivityManagerService  extends ActivityManagerNative
         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 final class ActivityManagerService  extends ActivityManagerNative
 
     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;
         }
     }
 
index a2f3372..cde17c9 100644 (file)
@@ -22,7 +22,6 @@ import com.android.server.am.ActivityStack.ActivityState;
 
 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 @@ final class ActivityRecord {
     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 @@ final class ActivityRecord {
     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 @@ final class ActivityRecord {
             inHistory = false;
             if (task != null && !finishing) {
                 task.numActivities--;
-                task = null;
             }
             clearOptionsLocked();
         }
@@ -542,7 +538,7 @@ final class ActivityRecord {
         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 @@ final class ActivityRecord {
         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(' ');
index e0b8015..526b24f 100644 (file)
@@ -21,23 +21,18 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 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;
 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.os.UserHandle;
 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 @@ final class ActivityStack {
     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 @@ final class ActivityStack {
     // 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 class ActivityStack {
     final boolean mMainStack;
     
     final Context mContext;
-
-    /**
-     * The back history of all previous (and possibly still
-     * running) activities.  It contains #ActivityRecord objects.
-     */
-    private final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
-
+    
     /**
      * The back history of all previous (and possibly still
-     * running) activities.  It contains #TaskRecord objects.
+     * running) activities.  It contains HistoryRecord 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 @@ final class ActivityStack {
     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 class ActivityStack {
 
     final Handler mHandler;
 
-    String mLastHistoryModifier;
-
     final class ActivityStackHandler extends Handler {
         //public Handler() {
         //    if (localLOGV) Slog.v(TAG, "Handler started!");
@@ -473,66 +444,26 @@ final class ActivityStack {
     }
 
     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 @@ final class ActivityStack {
      * @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;
+    final int indexOfTokenLocked(IBinder token) {
+        return mHistory.indexOf(ActivityRecord.forToken(token));
     }
 
-    private final int indexOfTokenLocked(IBinder token) {
-        return mHistory.indexOf(ActivityRecord.forToken(token));
+    final int indexOfActivityLocked(ActivityRecord r) {
+        return mHistory.indexOf(r);
     }
 
     final ActivityRecord isInStackLocked(IBinder token) {
-        ActivityRecord newAr = newIsInStackLocked(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 @@ final class ActivityStack {
      * @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 @@ final class ActivityStack {
             }
         }
         // 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 @@ final class ActivityStack {
                 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 @@ final class ActivityStack {
             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 @@ final class ActivityStack {
 
             // 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 @@ final class ActivityStack {
         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 @@ final class ActivityStack {
         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 @@ final class ActivityStack {
 
         // 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 @@ final class ActivityStack {
             
             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 @@ final class ActivityStack {
         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 @@ final class ActivityStack {
                             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 @@ final class ActivityStack {
             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 @@ final class ActivityStack {
                 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 @@ final class ActivityStack {
         } 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 @@ final class ActivityStack {
         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 @@ final class ActivityStack {
      */
     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 @@ final class ActivityStack {
                             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 @@ final class ActivityStack {
                             }
                             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 @@ final class ActivityStack {
                             // 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 @@ final class ActivityStack {
                     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 @@ final class ActivityStack {
                         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 @@ final class ActivityStack {
             }
         }
 
-        if (VALIDATE_TASK_REPLACE) {
-            verifyActivityRecords(true);
-        }
         return taskTop;
     }
     
@@ -2627,7 +2368,7 @@ final class ActivityStack {
                 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 @@ final class ActivityStack {
      */
     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 @@ final class ActivityStack {
                     + 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 @@ final class ActivityStack {
             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 @@ final class ActivityStack {
                 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 @@ final class ActivityStack {
                 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 @@ final class ActivityStack {
             }
 
             // Get the activity record.
-            int index = mHistory.indexOf(r);
+            int index = indexOfActivityLocked(r);
             if (index >= 0) {
                 res = r;
 
@@ -3851,9 +3579,9 @@ final class ActivityStack {
                 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 @@ final class ActivityStack {
         // 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 @@ final class ActivityStack {
         // 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 @@ final class ActivityStack {
 
         // 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 @@ final class ActivityStack {
 
         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 @@ final class ActivityStack {
         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 @@ final class ActivityStack {
      * @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 @@ final class ActivityStack {
             // 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 @@ final class ActivityStack {
 
     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 @@ final class ActivityStack {
                 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 @@ final class ActivityStack {
             // 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 @@ final class ActivityStack {
             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 @@ final class ActivityStack {
                     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 @@ final class ActivityStack {
         }
     }
     
-    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 @@ final class ActivityStack {
             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 @@ final class ActivityStack {
      * 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 @@ final class ActivityStack {
             }
         }
         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 @@ final class ActivityStack {
         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 @@ final class ActivityStack {
                 }
                 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 @@ final class ActivityStack {
         } 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 class ActivityStack {
      */
     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 @@ final class ActivityStack {
             }
         }
 
+        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 @@ final class ActivityStack {
                 }
                 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 @@ final class ActivityStack {
             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 @@ final class ActivityStack {
         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 @@ final class ActivityStack {
         }
         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 @@ final class ActivityStack {
     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;
-    }
 }
index 863bdad..3a6492e 100644 (file)
@@ -295,8 +295,20 @@ public class CompatModePackages {
             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--) {
index c460791..ed478c9 100644 (file)
@@ -27,13 +27,13 @@ import java.util.HashSet;
 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;
     }
 }
index f9b0d4c..1bae9ca 100644 (file)
@@ -23,7 +23,6 @@ import android.os.UserHandle;
 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 @@ class TaskRecord extends ThumbnailHolder {
 
     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 @@ class TaskRecord extends ThumbnailHolder {
             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 @@ class TaskRecord extends ThumbnailHolder {
             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 @@ class TaskRecord extends ThumbnailHolder {
                 pw.print((getInactiveDuration()/1000)); pw.println("s)");
     }
 
-    @Override
     public String toString() {
         if (stringName != null) {
             return stringName;
@@ -214,21 +156,19 @@ class TaskRecord extends ThumbnailHolder {
         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();
     }
index 8cc1d02..fbb5013 100644 (file)
@@ -30,10 +30,6 @@ import android.view.View;
 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
index 6aae202..59e4b0e 100644 (file)
 
 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 @@ class DisplayContentList extends ArrayList<DisplayContent> {
  * WindowManagerService.mWindowMap.
  */
 class DisplayContent {
-//    private final static String TAG = "DisplayContent";
 
     /** Unique identifier of this stack. */
     private final int mDisplayId;
@@ -74,26 +67,6 @@ class DisplayContent {
     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 @@ class DisplayContent {
         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 @@ class DisplayContent {
             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 (file)
index 1f1dd58..0000000
+++ /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 (file)
index 67dfa4f..0000000
+++ /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;
-    }
-}
index 67daf75..3964782 100644 (file)
@@ -10,8 +10,6 @@ import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPA
 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.SurfaceControl;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 
-import com.android.server.wm.DisplayContent.AppTokenIterator;
 import com.android.server.wm.WindowManagerService.DisplayContentsIterator;
 import com.android.server.wm.WindowManagerService.LayoutFields;
 
@@ -175,12 +172,12 @@ public class WindowAnimator {
         }
     }
 
-    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 @@ public class WindowAnimator {
             }
         }
 
-        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 @@ public class WindowAnimator {
 
     /** 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 @@ public class WindowAnimator {
         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 @@ public class WindowAnimator {
                 }
             }
 
+            testTokenMayBeDrawnLocked();
+
             for (int i = 0; i < numDisplays; i++) {
                 final int displayId = mDisplayContentsAnimators.keyAt(i);
-
-                testTokenMayBeDrawnLocked(displayId);
-
                 DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
 
                 final ScreenRotationAnimation screenRotationAnimation =
index 086da37..a6ce54c 100644 (file)
@@ -58,7 +58,6 @@ import com.android.server.display.DisplayManagerService;
 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 @@ public class WindowManagerService extends IWindowManager.Stub
     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 @@ public class WindowManagerService extends IWindowManager.Stub
     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 @@ public class WindowManagerService extends IWindowManager.Stub
     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 @@ public class WindowManagerService extends IWindowManager.Stub
     /**
      * 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 @@ public class WindowManagerService extends IWindowManager.Stub
 
     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 @@ public class WindowManagerService extends IWindowManager.Stub
         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 @@ public class WindowManagerService extends IWindowManager.Stub
                         + 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 @@ public class WindowManagerService extends IWindowManager.Stub
                     } 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 @@ public class WindowManagerService extends IWindowManager.Stub
                         } 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 @@ public class WindowManagerService extends IWindowManager.Stub
             } 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 @@ public class WindowManagerService extends IWindowManager.Stub
             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 class WindowManagerService extends IWindowManager.Stub
 
     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 @@ public class WindowManagerService extends IWindowManager.Stub
     // 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--;
-                }
-            }
-
-            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));
+            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);
             }
+            m--;
         }
     }
 
@@ -3227,7 +3226,6 @@ public class WindowManagerService extends IWindowManager.Stub
 
         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 @@ public class WindowManagerService extends IWindowManager.Stub
 
                     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 @@ public class WindowManagerService extends IWindowManager.Stub
                             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 @@ public class WindowManagerService extends IWindowManager.Stub
                     }
 
                     if (delayed) {
-                        displayContent.mExitingTokens.add(wtoken);
+                        mExitingTokens.add(wtoken);
                     } else if (wtoken.windowType == TYPE_WALLPAPER) {
                         mWallpaperTokens.remove(wtoken);
                     }
@@ -3279,9 +3277,27 @@ public class WindowManagerService extends IWindowManager.Stub
         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 @@ public class WindowManagerService extends IWindowManager.Stub
             }
             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 @@ public class WindowManagerService extends IWindowManager.Stub
         }
 
         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 @@ public class WindowManagerService extends IWindowManager.Stub
         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 @@ public class WindowManagerService extends IWindowManager.Stub
                         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 @@ public class WindowManagerService extends IWindowManager.Stub
                 }
                 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 @@ public class WindowManagerService extends IWindowManager.Stub
     }
 
     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 @@ public class WindowManagerService extends IWindowManager.Stub
         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(displayContent.getWindowList());
+            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/)) {
+                assignLayersLocked(windows);
+            }
         }
 
-        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) {
+    @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();
-        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");
+        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;
+                    }
                 }
-                displayContent.mTaskLists.add(taskList);
-
-                moveTaskWindowsLocked(taskId);
             }
-        } finally {
-            Binder.restoreCallingIdentity(origId);
+
+            mAnimatingAppTokens.clear();
+            mAnimatingAppTokens.addAll(mAppTokens);
+            moveAppWindowsLocked(tokens, mAppTokens.size());
         }
+        Binder.restoreCallingIdentity(origId);
     }
 
-    public void moveTaskToBottom(int taskId) {
+    @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();
-        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");
+        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++;
                 }
-                displayContent.mTaskLists.add(0, taskList);
-
-                moveTaskWindowsLocked(taskId);
             }
-        } finally {
-            Binder.restoreCallingIdentity(origId);
+
+            mAnimatingAppTokens.clear();
+            mAnimatingAppTokens.addAll(mAppTokens);
+            moveAppWindowsLocked(tokens, 0);
         }
+        Binder.restoreCallingIdentity(origId);
     }
 
     // -------------------------------------------------------------
@@ -4717,9 +4817,9 @@ public class WindowManagerService extends IWindowManager.Stub
     @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 @@ public class WindowManagerService extends IWindowManager.Stub
             // 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 @@ public class WindowManagerService extends IWindowManager.Stub
         }
 
         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 @@ public class WindowManagerService extends IWindowManager.Stub
     // 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 @@ public class WindowManagerService extends IWindowManager.Stub
                         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 @@ public class WindowManagerService extends IWindowManager.Stub
                 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 @@ public class WindowManagerService extends IWindowManager.Stub
         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 @@ public class WindowManagerService extends IWindowManager.Stub
         // 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 @@ public class WindowManagerService extends IWindowManager.Stub
                 }
             }
             Slog.w(TAG, "Current app token list:");
-            dumpAppTokensLocked();
+            dumpAnimatingAppTokensLocked();
             Slog.w(TAG, "Final window list:");
             dumpWindowsLocked();
         }
@@ -8105,11 +8204,11 @@ public class WindowManagerService extends IWindowManager.Stub
 
         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 @@ public class WindowManagerService extends IWindowManager.Stub
         }
     }
 
-    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 @@ public class WindowManagerService extends IWindowManager.Stub
         }
 
         // 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 @@ public class WindowManagerService extends IWindowManager.Stub
             }
 
             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 @@ public class WindowManagerService extends IWindowManager.Stub
                 if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
                     stopDimmingLocked(displayId);
                 }
+            }
 
-                if (updateAllDrawn) {
-                    updateAllDrawnLocked(displayContent);
-                }
+            if (updateAllDrawn) {
+                updateAllDrawnLocked();
             }
 
             if (focusDisplayed) {
@@ -8739,35 +8835,30 @@ public class WindowManagerService extends IWindowManager.Stub
         }
 
         // 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 @@ public class WindowManagerService extends IWindowManager.Stub
             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 @@ public class WindowManagerService extends IWindowManager.Stub
             // 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 @@ public class WindowManagerService extends IWindowManager.Stub
             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 @@ public class WindowManagerService extends IWindowManager.Stub
     }
 
     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 @@ public class WindowManagerService extends IWindowManager.Stub
             // 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 @@ public class WindowManagerService extends IWindowManager.Stub
                             TAG, "Reached focused app: " + mFocusedApp);
                         return null;
                     }
-                    nextApp = iterator.next();
+                    nextAppIndex--;
+                    nextApp = mAppTokens.get(nextAppIndex);
                     if (nextApp == thisApp) {
                         break;
                     }
@@ -9247,14 +9339,8 @@ public class WindowManagerService extends IWindowManager.Stub
                     // 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 @@ public class WindowManagerService extends IWindowManager.Stub
                 }
             }
         }
+        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 @@ public class WindowManagerService extends IWindowManager.Stub
                 }
             }
         }
+        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 @@ public class WindowManagerService extends IWindowManager.Stub
     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 @@ public class WindowManagerService extends IWindowManager.Stub
         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 @@ public class WindowManagerService extends IWindowManager.Stub
             } 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 @@ public class WindowManagerService extends IWindowManager.Stub
     class DisplayContentsIterator implements Iterator<DisplayContent> {
         private int cur;
 
-        void reset() {
-            cur = 0;
-        }
-
         @Override
         public boolean hasNext() {
             return cur < mDisplayContents.size();
@@ -10166,6 +10302,7 @@ public class WindowManagerService extends IWindowManager.Stub
         }
     }
 
+    final static boolean REVERSE_ITERATOR = true;
     class AllWindowsIterator implements Iterator<WindowState> {
         private DisplayContent mDisplayContent;
         private DisplayContentsIterator mDisplayContentsIterator;
@@ -10174,33 +10311,19 @@ public class WindowManagerService extends IWindowManager.Stub
         private boolean mReverse;
 
         AllWindowsIterator() {
-            this(false);
-        }
-
-        AllWindowsIterator(boolean reverse) {
             mDisplayContentsIterator = new DisplayContentsIterator();
-            reset(reverse);
+            mDisplayContent = mDisplayContentsIterator.next();
+            mWindowList = mDisplayContent.getWindowList();
         }
 
-        void reset(boolean reverse) {
+        AllWindowsIterator(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;
             }
index 517c4e4..a600623 100644 (file)
@@ -52,12 +52,6 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 
 class WindowList extends ArrayList<WindowState> {
-    WindowList() {
-        super();
-    }
-    WindowList(WindowList windows) {
-        super(windows);
-    }
 }
 
 /**
@@ -1092,7 +1086,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
         return true;
     }
 
-    public void setAppOpVisibilityLw(boolean state) {
+    public boolean setAppOpVisibilityLw(boolean state) {
         if (mAppOpVisibility != state) {
             mAppOpVisibility = state;
             if (state) {
@@ -1102,11 +1096,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
                 // 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
index 2267123..bd0ace8 100644 (file)
@@ -19,6 +19,7 @@ package com.android.server.wm;
 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
index 03871f6..746ac06 100644 (file)
@@ -222,7 +222,37 @@ public class WindowManagerPermissionTests extends TestCase {
         } catch (RemoteException e) {
             fail("Unexpected remote exception");
         }
-    }
+        
+        try {
+            mWm.moveAppToken(0, null);
+            fail("IWindowManager.moveAppToken did not throw SecurityException as"
+                    + " expected");
+        } catch (SecurityException e) {
+            // expected
+        } catch (RemoteException e) {
+            fail("Unexpected remote exception");
+        }
+        
+        try {
+            mWm.moveAppTokensToTop(null);
+            fail("IWindowManager.moveAppTokensToTop did not throw SecurityException as"
+                    + " expected");
+        } catch (SecurityException e) {
+            // expected
+        } catch (RemoteException e) {
+            fail("Unexpected remote exception");
+        }
+        
+        try {
+            mWm.moveAppTokensToBottom(null);
+            fail("IWindowManager.moveAppTokensToBottom did not throw SecurityException as"
+                    + " expected");
+        } catch (SecurityException e) {
+            // expected
+        } catch (RemoteException e) {
+            fail("Unexpected remote exception");
+        }
+       }    
 
     @SmallTest
     public void testDISABLE_KEYGUARD() {
index 278413e..59ae1a1 100644 (file)
@@ -210,6 +210,24 @@ public class IWindowManagerImpl implements IWindowManager {
     }
 
     @Override
+    public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
     public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
             throws RemoteException {
         // TODO Auto-generated method stub