Refactor moveStackWindowsLocked()

The method had multiple inner loops and was a less efficient form of
rebuildAppWindowsLocked(). Rewritten to use rebuildAppWindowsLocked()
and small other refactors.

Item #1 of bug 18088522.

Change-Id: If93fa961922c77c9f0af719e535ae5ca5d30fe59
This commit is contained in:
Craig Mautner
2015-01-14 10:33:48 -08:00
parent ea002666cf
commit 799bc1d383
3 changed files with 50 additions and 147 deletions

View File

@@ -107,7 +107,7 @@ class AppWindowToken extends WindowToken {
// Input application handle used by the input dispatcher.
final InputApplicationHandle mInputApplicationHandle;
boolean mDeferRemoval;
boolean mIsExiting;
boolean mLaunchTaskBehind;
boolean mEnteringAnimation;
@@ -304,11 +304,11 @@ class AppWindowToken extends WindowToken {
pw.print(prefix); pw.print("inPendingTransaction=");
pw.println(inPendingTransaction);
}
if (startingData != null || removed || firstWindowDrawn || mDeferRemoval) {
if (startingData != null || removed || firstWindowDrawn || mIsExiting) {
pw.print(prefix); pw.print("startingData="); pw.print(startingData);
pw.print(" removed="); pw.print(removed);
pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
pw.print(" mDeferRemoval="); pw.println(mDeferRemoval);
pw.print(" mIsExiting="); pw.println(mIsExiting);
}
if (startingWindow != null || startingView != null
|| startingDisplayed || startingMoved) {

View File

@@ -328,9 +328,9 @@ class DisplayContent {
AppTokenList tokens = task.mAppTokens;
for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
AppWindowToken wtoken = tokens.get(tokenNdx);
if (wtoken.mDeferRemoval) {
if (wtoken.mIsExiting) {
stack.mExitingAppTokens.remove(wtoken);
wtoken.mDeferRemoval = false;
wtoken.mIsExiting = false;
mService.removeAppFromTaskLocked(wtoken);
}
}

View File

@@ -153,6 +153,7 @@ import java.io.StringWriter;
import java.net.Socket;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
@@ -555,6 +556,10 @@ public class WindowManagerService extends IWindowManager.Stub
WindowState mInputMethodWindow = null;
final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
/** Temporary list for comparison. Always clear this after use so we don't end up with
* orphaned windows references */
final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
boolean mHardKeyboardAvailable;
boolean mShowImeWithHardKeyboard;
OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
@@ -4824,7 +4829,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
"removeAppToken make exiting: " + wtoken);
stack.mExitingAppTokens.add(wtoken);
wtoken.mDeferRemoval = true;
wtoken.mIsExiting = true;
} else {
// Make sure there is no animation running on this token,
// so any windows associated with it will be removed as
@@ -4874,39 +4879,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
WindowList windows = token.windows;
final int NW = windows.size();
if (NW > 0) {
mWindowsChanged = true;
}
int targetDisplayId = -1;
Task targetTask = mTaskIdToTask.get(token.appWindowToken.groupId);
if (targetTask != null) {
DisplayContent targetDisplayContent = targetTask.getDisplayContent();
if (targetDisplayContent != null) {
targetDisplayId = targetDisplayContent.getDisplayId();
}
}
for (int i = 0; i < NW; i++) {
WindowState win = windows.get(i);
if (targetDisplayId != -1 && win.getDisplayId() != targetDisplayId) {
continue;
}
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
win.getWindowList().remove(win);
int j = win.mChildWindows.size();
while (j > 0) {
j--;
WindowState cwin = win.mChildWindows.get(j);
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
"Tmp removing child window " + cwin);
cwin.getWindowList().remove(cwin);
}
}
return NW > 0;
}
void dumpAppTokensLocked() {
final int numStacks = mStackIdToStack.size();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
@@ -4938,90 +4910,20 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
private int findAppWindowInsertionPointLocked(AppWindowToken target) {
final int taskId = target.groupId;
Task targetTask = mTaskIdToTask.get(taskId);
if (targetTask == null) {
Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
+ taskId);
return 0;
}
DisplayContent displayContent = targetTask.getDisplayContent();
if (displayContent == null) {
Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
return 0;
}
final WindowList windows = displayContent.getWindowList();
final int NW = windows.size();
boolean found = false;
final ArrayList<Task> tasks = displayContent.getTasks();
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
final Task task = tasks.get(taskNdx);
if (!found && task.taskId != taskId) {
continue;
}
AppTokenList tokens = task.mAppTokens;
for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
final AppWindowToken wtoken = tokens.get(tokenNdx);
if (!found && wtoken == target) {
found = true;
}
if (found) {
// Find the first app token below the new position that has
// a window displayed.
if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
if (wtoken.sendingToBottom) {
if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
continue;
}
for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
WindowState win = wtoken.windows.get(i);
for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
WindowState cwin = win.mChildWindows.get(j);
if (cwin.mSubLayer >= 0) {
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;
}
}
}
}
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;
}
}
}
}
}
}
// Never put an app window underneath wallpaper.
for (int pos = NW - 1; pos >= 0; pos--) {
if (windows.get(pos).mIsWallpaper) {
if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
return pos + 1;
}
}
return 0;
}
private final int reAddWindowLocked(int index, WindowState win) {
final WindowList windows = win.getWindowList();
// Adding child windows relies on mChildWindows being ordered by mSubLayer.
final int NCW = win.mChildWindows.size();
boolean added = false;
boolean winAdded = false;
for (int j=0; j<NCW; j++) {
WindowState cwin = win.mChildWindows.get(j);
if (!added && cwin.mSubLayer >= 0) {
if (!winAdded && cwin.mSubLayer >= 0) {
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
+ index + ": " + cwin);
win.mRebuilding = false;
windows.add(index, win);
index++;
added = true;
winAdded = true;
}
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
+ index + ": " + cwin);
@@ -5029,7 +4931,7 @@ public class WindowManagerService extends IWindowManager.Stub
windows.add(index, cwin);
index++;
}
if (!added) {
if (!winAdded) {
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
+ index + ": " + win);
win.mRebuilding = false;
@@ -5054,41 +4956,40 @@ public class WindowManagerService extends IWindowManager.Stub
return index;
}
void tmpRemoveTaskWindowsLocked(Task task) {
AppTokenList tokens = task.mAppTokens;
for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
}
}
void moveStackWindowsLocked(DisplayContent displayContent) {
// First remove all of the windows from the list.
final ArrayList<Task> tasks = displayContent.getTasks();
final int numTasks = tasks.size();
for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
tmpRemoveTaskWindowsLocked(tasks.get(taskNdx));
}
final WindowList windows = displayContent.getWindowList();
mTmpWindows.addAll(windows);
// And now add them back at the correct place.
// Where to start adding?
for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
final int numTokens = tokens.size();
if (numTokens == 0) {
continue;
}
int pos = findAppWindowInsertionPointLocked(tokens.get(0));
for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
final AppWindowToken wtoken = tokens.get(tokenNdx);
if (wtoken != null) {
final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
if (newPos != pos) {
displayContent.layoutNeeded = true;
}
pos = newPos;
}
rebuildAppWindowListLocked(displayContent);
// Set displayContent.layoutNeeded if window order changed.
final int tmpSize = mTmpWindows.size();
final int winSize = windows.size();
int tmpNdx = 0, winNdx = 0;
while (tmpNdx < tmpSize && winNdx < winSize) {
// Skip over all exiting windows, they've been moved out of order.
WindowState tmp;
do {
tmp = mTmpWindows.get(tmpNdx++);
} while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
WindowState win;
do {
win = windows.get(winNdx++);
} while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
if (tmp != win) {
// Window order changed.
displayContent.layoutNeeded = true;
break;
}
}
if (tmpNdx != winNdx) {
// One list was different from the other.
displayContent.layoutNeeded = true;
}
mTmpWindows.clear();
if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/)) {
@@ -5229,7 +5130,7 @@ public class WindowManagerService extends IWindowManager.Stub
for (int appNdx = exitingApps.size() - 1; appNdx >= 0; --appNdx) {
final AppWindowToken wtoken = exitingApps.get(appNdx);
if (wtoken.groupId == taskId) {
wtoken.mDeferRemoval = false;
wtoken.mIsExiting = false;
exitingApps.remove(appNdx);
}
}
@@ -8640,7 +8541,7 @@ public class WindowManagerService extends IWindowManager.Stub
final int numTokens = tokens.size();
for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
final AppWindowToken wtoken = tokens.get(tokenNdx);
if (wtoken.mDeferRemoval) {
if (wtoken.mIsExiting) {
continue;
}
i = reAddAppWindowsLocked(displayContent, i, wtoken);
@@ -8650,6 +8551,7 @@ public class WindowManagerService extends IWindowManager.Stub
i -= lastBelow;
if (i != numRemoved) {
displayContent.layoutNeeded = true;
Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
numRemoved + " windows but added " + i,
new RuntimeException("here").fillInStackTrace());
@@ -8670,6 +8572,7 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.w(TAG, "Final window list:");
dumpWindowsLocked();
}
Arrays.fill(mRebuildTmp, null);
}
private final void assignLayersLocked(WindowList windows) {
@@ -10062,7 +9965,7 @@ public class WindowManagerService extends IWindowManager.Stub
mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
AppWindowToken token = exitingAppTokens.get(i);
if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
if (!token.hasVisible && !mClosingApps.contains(token) && !token.mIsExiting) {
// 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