Merge "Add AppWindowTokens to TaskList."
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 608ad1c..22af3d5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2838,11 +2838,8 @@
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);
}
}
@@ -8002,33 +7999,7 @@
}
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.
@@ -12370,7 +12341,6 @@
public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
Intent resultData) {
- ComponentName dest = destIntent.getComponent();
synchronized (this) {
ActivityRecord srec = ActivityRecord.forToken(token);
@@ -12378,87 +12348,7 @@
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 cde17c9..c1b406e 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -22,6 +22,7 @@
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 @@
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.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 @@
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 @@
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 @@
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 @@
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 @@
}
i++;
}
+ mService.mWindowManager.moveTaskToBottom(target.task.taskId);
if (taskTop == p) {
taskTop = below;
}
@@ -2304,6 +2301,8 @@
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 @@
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 @@
}
// Get the activity record.
- int index = indexOfActivityLocked(r);
+ int index = mHistory.indexOf(r);
if (index >= 0) {
res = r;
@@ -3654,7 +3653,7 @@
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (i=0; i<NS; i++) {
- ActivityRecord r = (ActivityRecord)stops.get(i);
+ ActivityRecord r = stops.get(i);
synchronized (mService) {
if (r.finishing) {
finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
@@ -3667,7 +3666,7 @@
// Finish any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (i=0; i<NF; i++) {
- ActivityRecord r = (ActivityRecord)finishes.get(i);
+ ActivityRecord r = finishes.get(i);
synchronized (mService) {
activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
}
@@ -3675,7 +3674,7 @@
// 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 @@
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 @@
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 @@
* @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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
+ mService.mWindowManager.moveTaskToTop(task);
finishTaskMoveLocked(task);
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
@@ -4532,6 +4661,7 @@
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
+ mService.mWindowManager.moveTaskToBottom(task);
finishTaskMoveLocked(task);
return true;
@@ -4561,9 +4691,8 @@
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 @@
}
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 @@
* 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 @@
/**
* 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 @@
/**
* 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 @@
AppTokenList appTokens = task.mAppTokens;
appTokens.remove(wtoken);
if (appTokens.size() == 0) {
+ mTaskLists.remove(task);
mTaskIdToTaskList.delete(taskId);
}
}
@@ -186,7 +195,7 @@
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 @@
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
similarity index 96%
rename from services/java/com/android/server/am/TaskGroup.java
rename to 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 03dcced..d51c07b 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.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 @@
/**
* 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,
@@ -3318,6 +3316,7 @@
mTaskIdToDisplayContents.put(taskId, displayContent);
}
displayContent.addAppToken(addPos, atoken);
+ displayContent.verifyAppTokens();
mTokenMap.put(token.asBinder(), atoken);
mTaskIdToDisplayContents.put(taskId, displayContent);
@@ -4301,11 +4300,12 @@
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
@@ -4315,7 +4315,8 @@
}
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;
@@ -4707,6 +4708,44 @@
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
// -------------------------------------------------------------