Merge "Revert "WindowList be gone!""

This commit is contained in:
Jorim Jaggi
2016-11-23 17:03:47 +00:00
committed by Android (Google) Code Review
14 changed files with 1607 additions and 729 deletions

View File

@@ -411,7 +411,7 @@ public class AppWindowAnimator {
}
if (mService.mInputMethodTarget != null
&& mService.mInputMethodTarget.mAppToken == mAppToken) {
mAppToken.getDisplayContent().computeImeTarget(true /* updateImeTarget */);
mAppToken.getDisplayContent().moveInputMethodWindowsIfNeeded(true);
}
if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken

View File

@@ -1006,7 +1006,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
tStartingWindow.mToken = this;
tStartingWindow.mAppToken = this;
if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
"Removing starting window: " + tStartingWindow);
getDisplayContent().removeFromWindowList(tStartingWindow);
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
"Removing starting " + tStartingWindow + " from " + fromToken);
fromToken.removeChild(tStartingWindow);
fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
@@ -1256,6 +1259,18 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
}
int rebuildWindowListUnchecked(int addIndex) {
return super.rebuildWindowList(addIndex);
}
@Override
int rebuildWindowList(int addIndex) {
if (mIsExiting && !waitingForReplacement()) {
return addIndex;
}
return rebuildWindowListUnchecked(addIndex);
}
@Override
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
// For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
@@ -1317,32 +1332,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
}
WindowState getImeTargetBelowWindow(WindowState w) {
final int index = mChildren.indexOf(w);
if (index > 0) {
final WindowState target = mChildren.get(index - 1);
if (target.canBeImeTarget()) {
return target;
}
}
return null;
}
WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
WindowState candidate = null;
for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
final WindowState w = mChildren.get(i);
if (w.mRemoved) {
continue;
}
if (candidate == null || w.mWinAnimator.mAnimLayer >
candidate.mWinAnimator.mAnimLayer) {
candidate = w;
}
}
return candidate;
}
@Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);

File diff suppressed because it is too large Load Diff

View File

@@ -16,15 +16,10 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
@@ -75,10 +70,6 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
// Array of window handles to provide to the input dispatcher.
private InputWindowHandle[] mInputWindowHandles;
private int mInputWindowHandleCount;
private boolean mAddInputConsumerHandle;
private boolean mAddPipInputConsumerHandle;
private boolean mAddWallpaperInputConsumerHandle;
private boolean mDisableWallpaperTouchEvents;
// Set to true when the first input device configuration change notification
// is received to indicate that the input devices are ready.
@@ -332,12 +323,12 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
}
}
void setUpdateInputWindowsNeededLw() {
public void setUpdateInputWindowsNeededLw() {
mUpdateInputWindowsNeeded = true;
}
/* Updates the cached window information provided to the input dispatcher. */
void updateInputWindowsLw(boolean force) {
public void updateInputWindowsLw(boolean force) {
if (!force && !mUpdateInputWindowsNeeded) {
return;
}
@@ -381,92 +372,15 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
}
// Add all windows on the default display.
updateInputWindows(inDrag);
if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
}
private void updateInputWindows(boolean inDrag) {
clearInputWindowHandlesLw();
// TODO: multi-display
final InputConsumerImpl navInputConsumer =
getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
final InputConsumerImpl pipInputConsumer =
getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
final InputConsumerImpl wallpaperInputConsumer =
getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
mAddInputConsumerHandle = navInputConsumer != null;
mAddPipInputConsumerHandle = pipInputConsumer != null;
mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
final Rect pipTouchableBounds = mAddPipInputConsumerHandle ? new Rect() : null;
mDisableWallpaperTouchEvents = false;
final WallpaperController wallpaperController = mService.mRoot.mWallpaperController;
mService.mRoot.forAllWindows(w -> {
final InputChannel inputChannel = w.mInputChannel;
final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
if (inputChannel == null || inputWindowHandle == null || w.mRemoved
|| w.isAdjustedForMinimizedDock()) {
// Skip this window because it cannot possibly receive input.
return;
}
if (mAddPipInputConsumerHandle
&& w.getStackId() == PINNED_STACK_ID
&& inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
// Update the bounds of the Pip input consumer to match the Pinned stack
w.getStack().getBounds(pipTouchableBounds);
pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
addInputWindowHandle(pipInputConsumer.mWindowHandle);
mAddPipInputConsumerHandle = false;
}
if (mAddInputConsumerHandle
&& inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
addInputWindowHandle(navInputConsumer.mWindowHandle);
mAddInputConsumerHandle = false;
}
if (mAddWallpaperInputConsumerHandle) {
if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
// Add the wallpaper input consumer above the first visible wallpaper.
addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
mAddWallpaperInputConsumerHandle = false;
}
}
final int flags = w.mAttrs.flags;
final int privateFlags = w.mAttrs.privateFlags;
final int type = w.mAttrs.type;
final boolean hasFocus = w == mInputFocus;
final boolean isVisible = w.isVisibleLw();
if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
mDisableWallpaperTouchEvents = true;
}
final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
&& (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
&& !mDisableWallpaperTouchEvents;
// If there's a drag in progress and 'child' is a potential drop target,
// make sure it's been told about the drag
if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
mService.mDragState.sendDragStartedIfNeededLw(w);
}
addInputWindowHandle(
inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
}, true /* traverseTopToBottom */);
if (mAddWallpaperInputConsumerHandle) {
// No visible wallpaper found, add the wallpaper input consumer at the end.
addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
}
mService.mRoot.updateInputWindows(this, mInputFocus, inDrag);
// Send windows to native code.
mService.mInputManager.setInputWindows(mInputWindowHandles);
// Clear the list in preparation for the next round.
clearInputWindowHandlesLw();
if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
}
/* Notifies that the input device configuration has changed. */

View File

@@ -219,7 +219,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
return false;
}
void getWindowsByName(ArrayList<WindowState> output, String name) {
void getWindowsByName(WindowList output, String name) {
int objectId = 0;
// See if this is an object ID.
try {
@@ -231,7 +231,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
getWindowsByName(output, name, objectId);
}
private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
private void getWindowsByName(WindowList output, String name, int objectId) {
forAllWindows((w) -> {
if (name != null) {
if (w.mAttrs.getTitle().toString().contains(name)) {
@@ -276,6 +276,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
return null;
}
// TODO: Users would have their own window containers under the display container?
void switchUser() {
final int count = mChildren.size();
for (int i = 0; i < count; ++i) {
final DisplayContent dc = mChildren.get(i);
dc.switchUser();
}
}
/**
* Set new display override config and return array of ids of stacks that were changed during
* update. If called for the default display, global configuration will also be updated.
@@ -420,6 +429,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
return hasChanges;
}
void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
final int count = mChildren.size();
for (int i = 0; i < count; ++i) {
final DisplayContent dc = mChildren.get(i);
dc.updateInputWindows(inputMonitor, inputFocus, inDrag);
}
}
boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
boolean secure) {
final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;

View File

@@ -589,6 +589,46 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
}
}
void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
DisplayContent.GetWindowOnDisplaySearchResult result) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final AppWindowToken current = mChildren.get(i);
if (current == token) {
// We have reach the token we are interested in. End search.
result.reachedToken = true;
return;
}
// We haven't reached the token yet; if this token is not going to the bottom and
// has windows on this display, then it is a candidate for what we are looking for.
final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
if (!current.sendingToBottom && tokenWindowList.size() > 0) {
result.foundWindow = tokenWindowList.get(0);
}
}
}
void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
DisplayContent.GetWindowOnDisplaySearchResult result) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final AppWindowToken current = mChildren.get(i);
if (!result.reachedToken) {
if (current == token) {
// We have reached the token we are interested in. Get whichever window occurs
// after it that is on the same display.
result.reachedToken = true;
}
continue;
}
final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
if (tokenWindowList.size() > 0) {
result.foundWindow = tokenWindowList.get(tokenWindowList.size() - 1);
return;
}
}
}
@Override
boolean fillsParent() {
return mFillsParent || !StackId.isTaskResizeAllowed(mStack.mStackId);

View File

@@ -859,9 +859,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
// TODO: Should each user have there own stacks?
@Override
void switchUser() {
super.switchUser();
int top = mChildren.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Task task = mChildren.get(taskNdx);
@@ -1490,6 +1488,30 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
}
void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
DisplayContent.GetWindowOnDisplaySearchResult result) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final Task task = mChildren.get(i);
task.getWindowOnDisplayBeforeToken(dc, token, result);
if (result.reachedToken) {
// We have reach the token we are interested in. End search.
return;
}
}
}
void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
DisplayContent.GetWindowOnDisplaySearchResult result) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final Task task = mChildren.get(i);
task.getWindowOnDisplayAfterToken(dc, token, result);
if (result.foundWindow != null) {
// We have found a window after the token. End search.
return;
}
}
}
@Override
int getOrientation() {
return (StackId.canSpecifyOrientation(mStackId))

View File

@@ -683,6 +683,24 @@ class WallpaperController {
}
}
void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
if (!mWallpaperTokens.isEmpty()) {
pw.println();
pw.print(prefix); pw.println("Wallpaper tokens:");
for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
WindowToken token = mWallpaperTokens.get(i);
pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
pw.print(' '); pw.print(token);
if (dumpAll) {
pw.println(':');
token.dump(pw, " ");
} else {
pw.println();
}
}
}
}
/** Helper class for storing the results of a wallpaper target find operation. */
final private static class FindWallpaperTargetResult {
WindowState topWallpaper = null;

View File

@@ -18,6 +18,7 @@ package com.android.server.wm;
import android.annotation.CallSuper;
import android.content.res.Configuration;
import android.view.animation.Animation;
import com.android.internal.util.ToBooleanFunction;
import java.util.Comparator;
@@ -482,11 +483,19 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
return false;
}
// TODO: Users would have their own window containers under the display container?
void switchUser() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
mChildren.get(i).switchUser();
/**
* Rebuilds the WindowList for the input display content.
* @param addIndex The index in the window list to add the next entry to.
* @return The next index in the window list to.
*/
// TODO: Hoping we can get rid of WindowList so this method wouldn't be needed.
int rebuildWindowList(int addIndex) {
final int count = mChildren.size();
for (int i = 0; i < count; i++) {
final WindowContainer wc = mChildren.get(i);
addIndex = wc.rebuildWindowList(addIndex);
}
return addIndex;
}
/**

View File

@@ -606,6 +606,17 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mInputMethodTargetWaitingAnim;
WindowState mInputMethodWindow = null;
// TODO: Remove with extreme prejudice! This list is maintained so that we can keep track of
// dialogs that should go on top of the IME so they can be re-arranged in the window list any
// time the IME changes position in the window list. Normally you would have a dialog be a child
// window of the IME, but they don't share the same token since they are added by different
// clients. This doesn't really affect what the user sees on screen since this dialogs have an
// higher base layer than the IME window, but it will affect users of the window list that
// expect the list to represent the order of things on-screen (e.g input service). This makes
// the code for managing the window list hard to follow (see all the places it is used).
// We can remove the use of this field when we automatically assign layers and z-order the
// window list before it is used whenever window container order changes.
final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>();
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
@@ -1366,16 +1377,19 @@ public class WindowManagerService extends IWindowManager.Stub
boolean imMayMove = true;
win.mToken.addWindow(win);
if (type == TYPE_INPUT_METHOD) {
win.mGivenInsetsPending = true;
mInputMethodWindow = win;
displayContent.computeImeTarget(true /* updateImeTarget */);
win.mToken.addImeWindow(win);
imMayMove = false;
} else if (type == TYPE_INPUT_METHOD_DIALOG) {
displayContent.computeImeTarget(true /* updateImeTarget */);
mInputMethodDialogs.add(win);
win.mToken.addWindow(win);
displayContent.moveInputMethodDialogs(
displayContent.findDesiredInputMethodWindowIndex(true));
imMayMove = false;
} else {
win.mToken.addWindow(win);
if (type == TYPE_WALLPAPER) {
displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -1448,7 +1462,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (imMayMove) {
displayContent.computeImeTarget(true /* updateImeTarget */);
displayContent.moveInputMethodWindowsIfNeeded(false);
}
// Don't do layout here, the window must call
@@ -1632,6 +1646,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (mInputMethodWindow == win) {
mInputMethodWindow = null;
} else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
mInputMethodDialogs.remove(win);
}
final WindowToken token = win.mToken;
@@ -1661,11 +1677,13 @@ public class WindowManagerService extends IWindowManager.Stub
dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
if (dc != null && !mWindowPlacerLocked.isInLayout()) {
dc.assignWindowLayers(true /* setLayoutNeeded */);
mWindowPlacerLocked.performSurfacePlacement();
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
if (dc != null && dc.removeFromWindowList(win)) {
if (!mWindowPlacerLocked.isInLayout()) {
dc.assignWindowLayers(true /* setLayoutNeeded */);
mWindowPlacerLocked.performSurfacePlacement();
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
}
}
}
@@ -2046,15 +2064,14 @@ public class WindowManagerService extends IWindowManager.Stub
// reassign them at this point if the IM window state gets shuffled
boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
final DisplayContent dc = win.getDisplayContent();
if (imMayMove) {
dc.computeImeTarget(true /* updateImeTarget */);
if (toBeDisplayed) {
// Little hack here -- we -should- be able to rely on the function to return
// true if the IME has moved and needs its layer recomputed. However, if the IME
// was hidden and isn't actually moved in the list, its layer may be out of data
// so we make sure to recompute it.
dc.assignWindowLayers(false /* setLayoutNeeded */);
}
if (imMayMove && (dc.moveInputMethodWindowsIfNeeded(false) || toBeDisplayed)) {
// Little hack here -- we -should- be able to rely on the function to return true if
// the IME has moved and needs its layer recomputed. However, if the IME was hidden
// and isn't actually moved in the list, its layer may be out of data so we make
// sure to recompute it.
// TODO: Probably not needed once the window list always has the right z-ordering
// when the window hierarchy is updated.
dc.assignWindowLayers(false /* setLayoutNeeded */);
}
if (wallpaperMayMove) {
@@ -3334,7 +3351,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mAppTransition.isTransitionSet()) {
task.setSendingToBottom(false);
}
displayContent.layoutAndAssignWindowLayersIfNeeded();
displayContent.rebuildAppWindowsAndLayoutIfNeeded();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -3356,7 +3373,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mAppTransition.isTransitionSet()) {
task.setSendingToBottom(true);
}
stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
stack.getDisplayContent().rebuildAppWindowsAndLayoutIfNeeded();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -4602,7 +4619,7 @@ public class WindowManagerService extends IWindowManager.Stub
return null;
}
}
return displayContent.screenshotApplications(appToken, width, height,
return displayContent.screenshotApplications(appToken, displayId, width, height,
includeFullDisplay, frameScale, config, wallpaperOnly);
}
@@ -5164,7 +5181,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean result = true;
final ArrayList<WindowState> windows = new ArrayList();
final WindowList windows = new WindowList();
synchronized (mWindowMap) {
mRoot.forAllWindows(w -> {
windows.add(w);
@@ -7295,7 +7312,7 @@ public class WindowManagerService extends IWindowManager.Stub
changes |= FINISH_LAYOUT_REDO_LAYOUT;
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
"Wallpaper layer changed: assigning layers + relayout");
dc.computeImeTarget(true /* updateImeTarget */);
dc.moveInputMethodWindowsIfNeeded(true);
mRoot.mWallpaperMayChange = true;
// Since the window list has been rebuilt, focus might have to be recomputed since the
// actual order of windows might have changed again.
@@ -7388,25 +7405,10 @@ public class WindowManagerService extends IWindowManager.Stub
mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
// TODO(multidisplay): Focused windows on default display only.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
boolean imWindowChanged = false;
if (mInputMethodWindow != null) {
final WindowState prevTarget = mInputMethodTarget;
final WindowState newTarget =
displayContent.computeImeTarget(true /* updateImeTarget*/);
imWindowChanged = prevTarget != newTarget;
if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
&& mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
displayContent.assignWindowLayers(false /* setLayoutNeeded */);
imWindowChanged |=
prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
}
}
final boolean imWindowChanged = displayContent.moveInputMethodWindowsIfNeeded(
mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
&& mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
if (imWindowChanged) {
mWindowsChanged = true;
displayContent.setLayoutNeeded();
newFocus = mRoot.computeFocusedWindow();
}
@@ -7881,6 +7883,7 @@ public class WindowManagerService extends IWindowManager.Stub
private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
mRoot.dumpTokens(pw, dumpAll);
mRoot.mWallpaperController.dumpTokens(pw, " ", dumpAll);
if (!mFinishedStarting.isEmpty()) {
pw.println();
pw.println(" Finishing start of application tokens:");
@@ -7926,6 +7929,16 @@ public class WindowManagerService extends IWindowManager.Stub
ArrayList<WindowState> windows) {
mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
if (mInputMethodDialogs.size() > 0) {
pw.println();
pw.println(" Input method dialogs:");
for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
WindowState w = mInputMethodDialogs.get(i);
if (windows == null || windows.contains(w)) {
pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
}
}
}
if (mPendingRemove.size() > 0) {
pw.println();
pw.println(" Remove pending for:");
@@ -8084,7 +8097,7 @@ public class WindowManagerService extends IWindowManager.Stub
private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
boolean dumpAll) {
final ArrayList<WindowState> windows = new ArrayList();
final WindowList windows = new WindowList();
if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
final boolean appsOnly = name.contains("apps");
final boolean visibleOnly = name.contains("visible");

View File

@@ -76,7 +76,6 @@ import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -116,7 +115,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIO
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -142,6 +140,9 @@ import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
class WindowList extends ArrayList<WindowState> {
}
/** A window in the window manager. */
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
@@ -447,6 +448,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
boolean mWindowRemovalAllowed;
/**
* Temp for keeping track of windows that have been removed when
* rebuilding window list.
*/
boolean mRebuilding;
// Input channel and input window handle used by the input dispatcher.
final InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
@@ -1714,7 +1721,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final DisplayContent dc = getDisplayContent();
if (mService.mInputMethodTarget == this) {
dc.computeImeTarget(true /* updateImeTarget */);
dc.moveInputMethodWindowsIfNeeded(false);
}
final int type = mAttrs.type;
@@ -1924,33 +1931,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mLayer + specialAdjustment;
}
boolean canBeImeTarget() {
final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
final int type = mAttrs.type;
if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
&& type != TYPE_APPLICATION_STARTING) {
return false;
}
if (DEBUG_INPUT_METHOD) {
Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding());
if (!isVisibleOrAdding()) {
Slog.i(TAG_WM, " mSurfaceController=" + mWinAnimator.mSurfaceController
+ " relayoutCalled=" + mRelayoutCalled
+ " viewVis=" + mViewVisibility
+ " policyVis=" + mPolicyVisibility
+ " policyVisAfterAnim=" + mPolicyVisibilityAfterAnim
+ " parentHidden=" + isParentWindowHidden()
+ " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
if (mAppToken != null) {
Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
}
}
}
return isVisibleOrAdding();
}
void scheduleAnimationIfDimming() {
final DisplayContent dc = getDisplayContent();
if (dc == null) {
@@ -2105,7 +2085,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return false;
}
private void removeReplacedWindow() {
void removeReplacedWindow() {
if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
if (isDimming()) {
transferDimToReplacement();
@@ -2158,16 +2138,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
@Override
void switchUser() {
super.switchUser();
if (isHiddenFromUserLocked()) {
if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this
+ ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid);
hideLw(false);
}
}
int getTouchableRegion(Region region, int flags) {
final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
if (modal && mAppToken != null) {
@@ -3529,6 +3499,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mIsChildWindow;
}
/**
* Returns the bottom child window in regards to z-order of this window or null if no children.
*/
WindowState getBottomChild() {
// Child windows are z-ordered based on sub-layer using {@link #sWindowSubLayerComparator}
// and the child with the lowest z-order will be at the head of the list.
WindowState c = mChildren.peekFirst();
return c == null ? null : c;
}
boolean layoutInParentFrame() {
return mIsChildWindow
&& (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
@@ -3814,6 +3794,44 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return highestAnimLayer;
}
@Override
int rebuildWindowList(int addIndex) {
return reAddWindow(addIndex);
}
// TODO: come-up with a better name for this method that represents what it does.
// Or, it is probably not going to matter anyways if we are successful in getting rid of
// the WindowList concept.
int reAddWindow(int index) {
final DisplayContent dc = getDisplayContent();
// Adding child windows relies on child windows being ordered by mSubLayer using
// {@link #sWindowSubLayerComparator}.
final int childCount = mChildren.size();
boolean winAdded = false;
for (int j = 0; j < childCount; j++) {
final WindowState child = mChildren.get(j);
if (!winAdded && child.mSubLayer >= 0) {
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
"Re-adding child window at " + index + ": " + child);
mRebuilding = false;
dc.addToWindowList(this, index);
index++;
winAdded = true;
}
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + child);
child.mRebuilding = false;
dc.addToWindowList(child, index);
index++;
}
if (!winAdded) {
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + this);
mRebuilding = false;
dc.addToWindowList(this, index);
index++;
}
return index;
}
@Override
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
if (mChildren.isEmpty()) {

View File

@@ -239,8 +239,7 @@ class WindowSurfacePlacer {
mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
// TODO: Don't believe this is really needed...
//mService.mWindowsChanged = true;
displayContent.rebuildAppWindowList();
mService.mRoot.mWallpaperMayChange = false;
@@ -357,8 +356,12 @@ class WindowSurfacePlacer {
displayContent.setLayoutNeeded();
// TODO(multidisplay): IMEs are only supported on the default display.
// TODO: Probably not needed once the window list always has the right z-ordering
// when the window hierarchy is updated.
final DisplayContent dc = mService.getDefaultDisplayContentLocked();
dc.computeImeTarget(true /* updateImeTarget */);
if (!dc.moveInputMethodWindowsIfNeeded(true)) {
dc.assignWindowLayers(false /*setLayoutNeeded*/);
}
mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
true /*updateInputWindows*/);
mService.mFocusMayChange = false;

View File

@@ -168,6 +168,13 @@ class WindowToken extends WindowContainer<WindowState> {
return highestAnimLayer;
}
WindowState getTopWindow() {
if (mChildren.isEmpty()) {
return null;
}
return (WindowState) mChildren.get(mChildren.size() - 1).getTop();
}
/**
* Returns true if the new window is considered greater than the existing window in terms of
* z-order.
@@ -182,16 +189,51 @@ class WindowToken extends WindowContainer<WindowState> {
if (DEBUG_FOCUS) Slog.d(TAG_WM,
"addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
if (win.isChildWindow()) {
// Child windows are added to their parent windows.
if (!win.isChildWindow()) {
if (asAppWindowToken() != null) {
mDisplayContent.addAppWindowToWindowList(win);
} else {
mDisplayContent.addNonAppWindowToWindowList(win);
}
if (!mChildren.contains(win)) {
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
addChild(win, mWindowComparator);
}
} else {
mDisplayContent.addChildWindowToWindowList(win);
}
}
void addImeWindow(WindowState win) {
int pos = mDisplayContent.findDesiredInputMethodWindowIndex(true);
if (pos < 0) {
addWindow(win);
mDisplayContent.moveInputMethodDialogs(pos);
return;
}
if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
"Adding input method window " + win + " at " + pos);
mDisplayContent.addToWindowList(win, pos);
if (!mChildren.contains(win)) {
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
addChild(win, mWindowComparator);
mService.mWindowsChanged = true;
// TODO: Should we also be setting layout needed here and other places?
addChild(win, null);
}
mDisplayContent.moveInputMethodDialogs(pos + 1);
}
/** Return the first window in the token window list that isn't a starting window or null. */
WindowState getFirstNonStartingWindow() {
final int count = mChildren.size();
// We only care about parent windows so no need to loop through child windows.
for (int i = 0; i < count; i++) {
final WindowState w = mChildren.get(i);
if (w.mAttrs.type != TYPE_APPLICATION_STARTING) {
return w;
}
}
return null;
}
/** Returns true if the token windows list is empty. */

View File

@@ -116,6 +116,35 @@ public class WindowStateTests extends WindowTestsBase {
assertFalse(win2.hasChild(randomWindow));
}
@Test
public void testGetBottomChild() throws Exception {
final WindowState parentWindow =
createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
assertNull(parentWindow.getBottomChild());
final WindowState child1 =
createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child1");
assertEquals(child1, parentWindow.getBottomChild());
final WindowState child2 =
createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child2");
// Since child1 and child2 are at the same layer, then child2 is expect to be added on top
// on child1
assertEquals(child1, parentWindow.getBottomChild());
final WindowState child3 =
createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child3");
// Since child3 is a negative layer, we would expect it to be added below current children
// with positive layers.
assertEquals(child3, parentWindow.getBottomChild());
final WindowState child4 =
createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child4");
// We would also expect additional negative layers to be added below existing negative
// layers.
assertEquals(child4, parentWindow.getBottomChild());
}
@Test
public void testGetParentWindow() throws Exception {
final WindowState parentWindow =