diff options
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 118 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityRecord.java | 5 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityStack.java | 200 | ||||
-rw-r--r-- | services/java/com/android/server/wm/DisplayContent.java | 145 | ||||
-rw-r--r-- | services/java/com/android/server/wm/TaskGroup.java (renamed from services/java/com/android/server/am/TaskGroup.java) | 2 | ||||
-rw-r--r-- | services/java/com/android/server/wm/TaskList.java | 12 | ||||
-rw-r--r-- | services/java/com/android/server/wm/WindowManagerService.java | 49 |
7 files changed, 358 insertions, 173 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 9a64a7e..f62c3d3 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2838,11 +2838,8 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<activities.size(); i++) { ActivityRecord r = activities.get(i); if (!r.finishing) { - int index = mMainStack.indexOfTokenLocked(r.appToken); - if (index >= 0) { - mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED, - null, "finish-heavy", true); - } + mMainStack.finishActivityLocked(r, Activity.RESULT_CANCELED, + null, "finish-heavy", true); } } @@ -8001,33 +7998,7 @@ public final class ActivityManagerService extends ActivityManagerNative } mMainStack.resumeTopActivityLocked(null); } else { - 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 = mMainStack.getActivityAtIndex(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); - } - } - } - } + mMainStack.finishTopRunningActivityLocked(app); } // Bump up the crash count of any services currently running in the proc. @@ -12364,7 +12335,6 @@ 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); @@ -12372,87 +12342,7 @@ public final class ActivityManagerService extends ActivityManagerNative return false; } ActivityStack stack = srec.stack; - final int start = stack.indexOfActivityLocked(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 = stack.getActivityAtIndex(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 = stack.getActivityAtIndex(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 = stack.getActivityAtIndex(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; + return stack.navigateUpToLocked(srec, destIntent, resultCode, resultData); } } diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index ba2e47a..2ea79b8 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -22,6 +22,7 @@ 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; @@ -95,9 +96,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 results; // pending ActivityResult objs we have received + ArrayList<ResultInfo> results; // pending ActivityResult objs we have received HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act - ArrayList newIntents; // any pending new intents for single-top mode + ArrayList<Intent> 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. diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index d969709..76836f9 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -24,11 +24,13 @@ 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; @@ -501,14 +503,10 @@ final class ActivityStack { return null; } - final int indexOfTokenLocked(IBinder 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 r = ActivityRecord.forToken(token); if (mHistory.contains(r)) { @@ -517,14 +515,6 @@ final class ActivityStack { return null; } - // TODO: This exposes mHistory too much, replace usage with ActivityStack methods. - final ActivityRecord getActivityAtIndex(int index) { - if (index >= 0 && index < mHistory.size()) { - return mHistory.get(index); - } - return null; - } - int getTaskForActivityLocked(IBinder token, boolean onlyRoot) { TaskRecord lastTask = null; final int N = mHistory.size(); @@ -745,7 +735,13 @@ final class ActivityStack { try { profileFd = profileFd.dup(); } catch (IOException e) { - profileFd = null; + if (profileFd != null) { + try { + profileFd.close(); + } catch (IOException o) { + } + profileFd = null; + } } } app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, @@ -1758,7 +1754,7 @@ final class ActivityStack { try { // Deliver all pending results. - ArrayList a = next.results; + ArrayList<ResultInfo> a = next.results; if (a != null) { final int N = a.size(); if (!next.finishing && N > 0) { @@ -2156,6 +2152,7 @@ final class ActivityStack { } i++; } + mService.mWindowManager.moveTaskToBottom(target.task.taskId); if (taskTop == p) { taskTop = below; } @@ -2304,6 +2301,8 @@ final class ActivityStack { validateAppTokensLocked(); } } + // TODO: This is wrong because it doesn't take lastReparentPos into account. + mService.mWindowManager.moveTaskToTop(task.taskId); replyChainEnd = -1; // Now we've moved it in to place... but what if this is @@ -2413,7 +2412,7 @@ final class ActivityStack { if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) { if (!ret.finishing) { - int index = indexOfTokenLocked(ret.appToken); + int index = mHistory.indexOf(ret); if (index >= 0) { finishActivityLocked(ret, index, Activity.RESULT_CANCELED, null, "clear", false); @@ -3568,7 +3567,7 @@ final class ActivityStack { } // Get the activity record. - int index = indexOfActivityLocked(r); + int index = mHistory.indexOf(r); if (index >= 0) { res = r; @@ -3654,7 +3653,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 = (ActivityRecord)stops.get(i); + ActivityRecord r = stops.get(i); synchronized (mService) { if (r.finishing) { finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false); @@ -3667,7 +3666,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 = (ActivityRecord)finishes.get(i); + ActivityRecord r = finishes.get(i); synchronized (mService) { activityRemoved = destroyActivityLocked(r, true, false, "finish-idle"); } @@ -3675,7 +3674,7 @@ final class ActivityStack { // Report back to any thumbnail receivers. for (i=0; i<NT; i++) { - ActivityRecord r = (ActivityRecord)thumbnails.get(i); + ActivityRecord r = thumbnails.get(i); mService.sendPendingThumbnail(r, null, null, null, true); } @@ -3730,7 +3729,7 @@ final class ActivityStack { int i; for (i=mHistory.size()-1; i>=0; i--) { - ActivityRecord r = (ActivityRecord)mHistory.get(i); + ActivityRecord r = mHistory.get(i); if (r.resultTo == self && r.requestCode == requestCode) { if ((r.resultWho == null && resultWho == null) || (r.resultWho != null && r.resultWho.equals(resultWho))) { @@ -3742,6 +3741,36 @@ 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( @@ -3800,6 +3829,19 @@ 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); @@ -3892,7 +3934,7 @@ final class ActivityStack { private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) { - final int index = indexOfActivityLocked(r); + final int index = mHistory.indexOf(r); if (index < 0) { return null; } @@ -3948,16 +3990,102 @@ 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 @@ -4216,7 +4344,7 @@ final class ActivityStack { mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); } - int index = indexOfActivityLocked(r); + int index = mHistory.indexOf(r); if (index >= 0) { if (r.state == ActivityState.DESTROYING) { cleanUpActivityLocked(r, true, false); @@ -4230,15 +4358,15 @@ final class ActivityStack { } } - private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app, - String listName) { + private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> 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 = (ActivityRecord)list.get(i); + ActivityRecord r = 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!"); @@ -4264,7 +4392,7 @@ final class ActivityStack { TAG, "Removing app " + app + " from history with " + i + " entries"); while (i > 0) { i--; - ActivityRecord r = (ActivityRecord)mHistory.get(i); + ActivityRecord r = mHistory.get(i); if (DEBUG_CLEANUP) Slog.v( TAG, "Record #" + i + " " + r + ": app=" + r.app); if (r.app == app) { @@ -4440,6 +4568,7 @@ final class ActivityStack { if (VALIDATE_TOKENS) { validateAppTokensLocked(); } + mService.mWindowManager.moveTaskToTop(task); finishTaskMoveLocked(task); EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task); @@ -4532,6 +4661,7 @@ final class ActivityStack { if (VALIDATE_TOKENS) { validateAppTokensLocked(); } + mService.mWindowManager.moveTaskToBottom(task); finishTaskMoveLocked(task); return true; @@ -4561,9 +4691,8 @@ 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, @@ -4643,6 +4772,7 @@ 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; diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index 906ea57..43a5f0c 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -16,12 +16,16 @@ package com.android.server.wm; +import android.os.Debug; +import android.util.Slog; 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> { } @@ -34,7 +38,7 @@ class DisplayContentList extends ArrayList<DisplayContent> { * WindowManagerService.mWindowMap. */ class DisplayContent { -// private final static String TAG = "DisplayContent"; + private final static String TAG = "DisplayContent"; /** Unique identifier of this stack. */ private final int mDisplayId; @@ -97,7 +101,7 @@ class DisplayContent { /** * Sorted most recent at top, oldest at [0]. */ -// ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>(); + ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>(); SparseArray<TaskList> mTaskIdToTaskList = new SparseArray<TaskList>(); /** @@ -133,24 +137,28 @@ class DisplayContent { /** * 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 atoken The token to insert. + * @param wtoken The token to insert. */ - void addAppToken(final int addPos, final AppWindowToken atoken) { - mAppTokens.add(addPos, atoken); + void addAppToken(final int addPos, final AppWindowToken wtoken) { + mAppTokens.add(addPos, wtoken); if (addPos == 0 || addPos == mAnimatingAppTokens.size()) { // It was inserted into the beginning or end of mAppTokens. Honor that. - mAnimatingAppTokens.add(addPos, atoken); + mAnimatingAppTokens.add(addPos, wtoken); } else { // 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); + mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), wtoken); } - TaskList task = mTaskIdToTaskList.get(atoken.groupId); + TaskList task = mTaskIdToTaskList.get(wtoken.groupId); if (task == null) { - mTaskIdToTaskList.put(atoken.groupId, new TaskList(atoken)); + task = new TaskList(wtoken, this); + mTaskIdToTaskList.put(wtoken.groupId, task); + mTaskLists.add(task); + } else { + task.mAppTokens.add(wtoken); } } @@ -163,6 +171,7 @@ class DisplayContent { AppTokenList appTokens = task.mAppTokens; appTokens.remove(wtoken); if (appTokens.size() == 0) { + mTaskLists.remove(task); mTaskIdToTaskList.delete(taskId); } } @@ -186,7 +195,7 @@ class DisplayContent { task = mTaskIdToTaskList.get(newTaskId); if (task == null) { - task = new TaskList(wtoken); + task = new TaskList(wtoken, this); mTaskIdToTaskList.put(newTaskId, task); } else { task.mAppTokens.add(wtoken); @@ -195,6 +204,122 @@ class DisplayContent { wtoken.groupId = newTaskId; } + class TaskListsIterator implements Iterator<TaskList> { + private int mCur; + private boolean mReverse; + + TaskListsIterator() { + this(false); + } + + TaskListsIterator(boolean reverse) { + mReverse = reverse; + int numTaskLists = mTaskLists.size(); + mCur = reverse ? numTaskLists - 1 : 0; + } + + @Override + public boolean hasNext() { + if (mReverse) { + return mCur >= 0; + } + return mCur < mTaskLists.size(); + } + + @Override + public TaskList next() { + if (hasNext()) { + TaskList taskList = mTaskLists.get(mCur); + mCur += (mReverse ? -1 : 1); + return taskList; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new IllegalArgumentException(); + } + } + + class AppTokenIterator implements Iterator<AppWindowToken> { + final TaskListsIterator mIterator; + final boolean mReverse; + int mCur; + TaskList mTaskList; + + public AppTokenIterator() { + this(false); + } + + public AppTokenIterator(boolean reverse) { + mReverse = reverse; + mIterator = new TaskListsIterator(reverse); + getNextTaskList(); + } + + private void getNextTaskList() { + if (mIterator.hasNext()) { + mTaskList = mIterator.next(); + mCur = mReverse ? mTaskList.mAppTokens.size() - 1 : 0; + } + } + + @Override + public boolean hasNext() { + if (mTaskList == null) { + return false; + } + if (mReverse) { + return mCur >= 0; + } + return mCur < mTaskList.mAppTokens.size(); + } + + @Override + public AppWindowToken next() { + if (hasNext()) { + AppWindowToken wtoken = mTaskList.mAppTokens.get(mCur); + mCur += mReverse ? -1 : 1; + if (!hasNext()) { + getNextTaskList(); + } + return wtoken; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new IllegalArgumentException(); + } + } + + void verifyAppTokens() { + AppTokenIterator iterator = new AppTokenIterator(); + for (int i = 0; i < mAppTokens.size(); ++i) { + if (!iterator.hasNext()) { + Slog.e(TAG, "compareAppTokens: More mAppTokens than TaskList tokens. Callers=" + + Debug.getCallers(4)); + while (i < mAppTokens.size()) { + Slog.e(TAG, "compareAppTokens: mAppTokens[" + i + "]=" + mAppTokens.get(i)); + i++; + } + return; + } + AppWindowToken appToken = mAppTokens.get(i); + AppWindowToken taskListToken = iterator.next(); + if (appToken != taskListToken) { + Slog.e(TAG, "compareAppTokens: Mismatch at " + i + " appToken=" + appToken + + " taskListToken=" + taskListToken + ". Callers=" + Debug.getCallers(4)); + } + } + if (iterator.hasNext()) { + Slog.e(TAG, "compareAppTokens: More TaskList tokens than mAppTokens Callers=" + + Debug.getCallers(4)); + } + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); final String subPrefix = " " + prefix; diff --git a/services/java/com/android/server/am/TaskGroup.java b/services/java/com/android/server/wm/TaskGroup.java index 7574103..5e82af2 100644 --- a/services/java/com/android/server/am/TaskGroup.java +++ b/services/java/com/android/server/wm/TaskGroup.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.am; +package com.android.server.wm; import android.view.IApplicationToken; diff --git a/services/java/com/android/server/wm/TaskList.java b/services/java/com/android/server/wm/TaskList.java index fe12b98..88791f2 100644 --- a/services/java/com/android/server/wm/TaskList.java +++ b/services/java/com/android/server/wm/TaskList.java @@ -16,15 +16,15 @@ package com.android.server.wm; -import com.android.server.am.TaskGroup; - -class TaskList extends TaskGroup { +class TaskList { // private final String TAG = "TaskGroup"; - AppTokenList mAppTokens = new AppTokenList(); + DisplayContent mDisplayContent; + final AppTokenList mAppTokens = new AppTokenList(); + final int taskId; - TaskList(AppWindowToken wtoken) { + TaskList(AppWindowToken wtoken, DisplayContent displayContent) { taskId = wtoken.groupId; - tokens.add(wtoken.appToken); mAppTokens.add(wtoken); + mDisplayContent = displayContent; } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 62eccdf..3dec9a4 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -54,7 +54,6 @@ import com.android.server.AttributeCache; import com.android.server.EventLogTags; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; -import com.android.server.am.TaskGroup; import com.android.server.display.DisplayManagerService; import com.android.server.input.InputManagerService; import com.android.server.power.PowerManagerService; @@ -330,8 +329,7 @@ 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>(); /** * List of window tokens that have finished starting their application, @@ -3286,6 +3284,7 @@ public class WindowManagerService extends IWindowManager.Stub mTaskIdToDisplayContents.put(taskId, displayContent); } displayContent.addAppToken(addPos, atoken); + displayContent.verifyAppTokens(); mTokenMap.put(token.asBinder(), atoken); mTaskIdToDisplayContents.put(taskId, displayContent); @@ -4269,11 +4268,12 @@ 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); - mTaskIdToDisplayContents.get(wtoken.groupId).mExitingAppTokens.add(wtoken); + displayContent.mExitingAppTokens.add(wtoken); } else { // Make sure there is no animation running on this token, // so any windows associated with it will be removed as @@ -4283,7 +4283,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " + wtoken); - mTaskIdToDisplayContents.get(wtoken.groupId).removeAppToken(wtoken); + displayContent.removeAppToken(wtoken); + displayContent.verifyAppTokens(); wtoken.removed = true; if (wtoken.startingData != null) { startingToken = wtoken; @@ -4675,6 +4676,44 @@ public class WindowManagerService extends IWindowManager.Stub Binder.restoreCallingIdentity(origId); } + public void moveTaskToTop(int taskId) { + DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId); + if (displayContent == null) { + Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + + " not found in mTaskIdToDisplayContents"); + return; + } + TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId); + if (taskList == null) { + Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskIdToTaskLists"); + return; + } + if (!displayContent.mTaskLists.remove(taskList)) { + Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskLists"); + } + displayContent.mTaskLists.add(taskList); + displayContent.verifyAppTokens(); + } + + public void moveTaskToBottom(int taskId) { + 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, "moveTaskToTopBottomtaskId=" + taskId + " not found in mTaskIdToTaskLists"); + return; + } + if (!displayContent.mTaskLists.remove(taskList)) { + Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId + " not found in mTaskLists"); + } + displayContent.mTaskLists.add(0, taskList); + displayContent.verifyAppTokens(); + } + // ------------------------------------------------------------- // Misc IWindowSession methods // ------------------------------------------------------------- |