Add AppWindowTokens to TaskList.
- Add/remove/move TaskLists from ActivityStack.
- Further isolate mHistory.
- Cleanup warnings by parameterizing ArrayList.
- Fix previous bugs.
Change-Id: Ife8c7b7347479c70f10467cc384283456149ac50
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/wm/TaskGroup.java b/services/java/com/android/server/wm/TaskGroup.java
new file mode 100644
index 0000000..5e82af2
--- /dev/null
+++ b/services/java/com/android/server/wm/TaskGroup.java
@@ -0,0 +1,26 @@
+/*
+ * 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>();
+}
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.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,
@@ -3286,6 +3284,7 @@
mTaskIdToDisplayContents.put(taskId, displayContent);
}
displayContent.addAppToken(addPos, atoken);
+ displayContent.verifyAppTokens();
mTokenMap.put(token.asBinder(), atoken);
mTaskIdToDisplayContents.put(taskId, displayContent);
@@ -4269,11 +4268,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
@@ -4283,7 +4283,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;
@@ -4675,6 +4676,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
// -------------------------------------------------------------