diff options
17 files changed, 1023 insertions, 1607 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index e4ecb5c8063b..f0c6241644d8 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -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 diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 22af3d5b3357..f226683ac14d 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -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; } } diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index a2f337296deb..cde17c9b39ba 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -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(' '); diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index e0b80150fe30..526b24f052b3 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -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; - } } diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java index 863bdad42177..3a6492e2957b 100644 --- a/services/java/com/android/server/am/CompatModePackages.java +++ b/services/java/com/android/server/am/CompatModePackages.java @@ -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--) { diff --git a/services/java/com/android/server/am/PendingThumbnailsRecord.java b/services/java/com/android/server/am/PendingThumbnailsRecord.java index c4607916bb39..ed478c9741c8 100644 --- a/services/java/com/android/server/am/PendingThumbnailsRecord.java +++ b/services/java/com/android/server/am/PendingThumbnailsRecord.java @@ -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; } } diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index f9b0d4cfe93b..1bae9ca53adf 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -23,7 +23,6 @@ import android.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(); } diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java index 8cc1d0211132..fbb501397163 100644 --- a/services/java/com/android/server/wm/AppWindowToken.java +++ b/services/java/com/android/server/wm/AppWindowToken.java @@ -30,10 +30,6 @@ import android.view.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 diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index 6aae202d2309..59e4b0e6f730 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -16,17 +16,11 @@ package com.android.server.wm; -import static com.android.server.wm.WindowManagerService.FORWARD_ITERATOR; -import static com.android.server.wm.WindowManagerService.REVERSE_ITERATOR; - -import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Iterator; -import java.util.NoSuchElementException; class DisplayContentList extends ArrayList<DisplayContent> { } @@ -39,7 +33,6 @@ 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 index 1f1dd5832d55..000000000000 --- a/services/java/com/android/server/wm/TaskGroup.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import android.view.IApplicationToken; - -import java.util.ArrayList; - -public class TaskGroup { - public int taskId = -1; - public ArrayList<IApplicationToken> tokens = new ArrayList<IApplicationToken>(); - - @Override - public String toString() { - return "id=" + taskId + " tokens=" + tokens; - } -} diff --git a/services/java/com/android/server/wm/TaskList.java b/services/java/com/android/server/wm/TaskList.java deleted file mode 100644 index 67dfa4f333b4..000000000000 --- a/services/java/com/android/server/wm/TaskList.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -class TaskList { -// private final String TAG = "TaskGroup"; - DisplayContent mDisplayContent; - final AppTokenList mAppTokens = new AppTokenList(); - final int taskId; - - TaskList(AppWindowToken wtoken, DisplayContent displayContent) { - taskId = wtoken.groupId; - mAppTokens.add(wtoken); - mDisplayContent = displayContent; - } - - @Override - public String toString() { - return "id=" + taskId + " appTokens=" + mAppTokens; - } -} diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 67daf751d456..3964782baced 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -10,8 +10,6 @@ import static com.android.server.wm.WindowManagerService.LayoutFields.SET_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 = diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 086da37533d2..a6ce54cf7221 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -58,7 +58,6 @@ import com.android.server.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; } diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 517c4e414ada..a60062345cd9 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -52,12 +52,6 @@ import java.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 diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/java/com/android/server/wm/WindowToken.java index 22671234c538..bd0ace89e49d 100644 --- a/services/java/com/android/server/wm/WindowToken.java +++ b/services/java/com/android/server/wm/WindowToken.java @@ -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 diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index 03871f63db20..746ac0622300 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -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() { diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 278413e4395e..59ae1a1d4817 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -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 |