Switched WindowToken/AppWindowToken to use WindowContainer
Bug: 30060889
Change-Id: Ia82aedfd9ea86410acdcd3a55a7a7fc456be2fc3
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 66fa976..518b9b5 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -18,6 +18,7 @@
import static android.app.ActivityManager.StackId;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
@@ -149,29 +150,14 @@
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
- AppWindowToken(WindowManagerService service, IApplicationToken _token, boolean _voiceInteraction) {
- super(service, _token.asBinder(), WindowManager.LayoutParams.TYPE_APPLICATION, true);
- appToken = _token;
+ AppWindowToken(WindowManagerService service, IApplicationToken token, boolean _voiceInteraction) {
+ super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true);
+ appToken = token;
voiceInteraction = _voiceInteraction;
mInputApplicationHandle = new InputApplicationHandle(this);
mAppAnimator = new AppWindowAnimator(this, service);
}
- void sendAppVisibilityToClients() {
- final int count = windows.size();
- for (int i = 0; i < count; i++) {
- final WindowState win = windows.get(i);
- win.sendAppVisibilityToClients(clientHidden);
- }
- }
-
- void setVisibleBeforeClientHidden() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
- w.setVisibleBeforeClientHidden();
- }
- }
-
void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
firstWindowDrawn = true;
@@ -197,12 +183,12 @@
}
if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
- final int count = windows.size();
+ final int count = mChildren.size();
mReportedVisibilityResults.reset();
for (int i = 0; i < count; i++) {
- final WindowState win = windows.get(i);
+ final WindowState win = (WindowState) mChildren.get(i);
win.updateReportedVisibility(mReportedVisibilityResults);
}
@@ -280,9 +266,9 @@
changed = true;
}
- final int windowsCount = windows.size();
+ final int windowsCount = mChildren.size();
for (int i = 0; i < windowsCount; i++) {
- final WindowState win = windows.get(i);
+ final WindowState win = (WindowState) mChildren.get(i);
changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
}
@@ -317,8 +303,8 @@
delayed = true;
}
- for (int i = windows.size() - 1; i >= 0 && !delayed; i--) {
- if (windows.get(i).isWindowAnimationSet()) {
+ for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
+ if (((WindowState) mChildren.get(i)).isWindowAnimationSet()) {
delayed = true;
}
}
@@ -345,10 +331,10 @@
WindowState findMainWindow() {
WindowState candidate = null;
- int j = windows.size();
+ int j = mChildren.size();
while (j > 0) {
j--;
- final WindowState win = windows.get(j);
+ final WindowState win = (WindowState) mChildren.get(j);
final int type = win.mAttrs.type;
// No need to loop through child window as base application and starting types can't be
// child windows.
@@ -370,27 +356,6 @@
return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable;
}
- boolean isVisible() {
- final int count = windows.size();
- for (int i = 0; i < count; i++) {
- final WindowState win = windows.get(i);
- if (win.isVisible()) {
- return true;
- }
- }
- return false;
- }
-
- boolean canBeVisibleForCurrentUser() {
- for (int j = windows.size() - 1; j >= 0; j--) {
- final WindowState w = windows.get(j);
- if (!w.isHiddenFromUserLocked()) {
- return true;
- }
- }
- return false;
- }
-
void removeAppFromTaskLocked() {
mIsExiting = false;
removeAllWindows();
@@ -408,8 +373,8 @@
void clearAnimatingFlags() {
boolean wallpaperMightChange = false;
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState win = (WindowState) mChildren.get(i);
wallpaperMightChange |= win.clearAnimatingFlags();
}
if (wallpaperMightChange) {
@@ -432,8 +397,8 @@
*/
private void destroySurfaces(boolean cleanupOnResume) {
final DisplayContentList displayList = new DisplayContentList();
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState win = (WindowState) mChildren.get(i);
final boolean destroyed = win.destroySurface(cleanupOnResume, mAppStopped);
if (destroyed) {
@@ -491,9 +456,9 @@
return allDrawn;
}
- boolean canRestoreSurfaces() {
- for (int i = windows.size() -1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ private boolean canRestoreSurfaces() {
+ for (int i = mChildren.size() -1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
if (w.canRestoreSurface()) {
return true;
}
@@ -501,9 +466,9 @@
return false;
}
- void clearWasVisibleBeforeClientHidden() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ private void clearWasVisibleBeforeClientHidden() {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
w.clearWasVisibleBeforeClientHidden();
}
}
@@ -513,8 +478,8 @@
* animating with saved surface.
*/
boolean isAnimatingInvisibleWithSavedSurface() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
if (w.isAnimatingInvisibleWithSavedSurface()) {
return true;
}
@@ -527,16 +492,16 @@
* with a saved surface, and mark them destroying.
*/
void stopUsingSavedSurfaceLocked() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
w.stopUsingSavedSurface();
}
destroySurfaces();
}
void markSavedSurfaceExiting() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
w.markSavedSurfaceExiting();
}
}
@@ -550,8 +515,8 @@
// Check if all interesting windows are drawn and we can mark allDrawn=true.
int interestingNotDrawn = -1;
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
interestingNotDrawn = w.restoreSavedSurfaceForInterestingWindow();
}
@@ -569,8 +534,8 @@
}
void destroySavedSurfaces() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState win = (WindowState) mChildren.get(i);
win.destroySavedSurface();
}
}
@@ -589,12 +554,12 @@
if (startingWindow == win) {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
mService.scheduleRemoveStartingWindowLocked(this);
- } else if (windows.size() == 0 && startingData != null) {
+ } else if (mChildren.size() == 0 && startingData != null) {
// If this is the last window and we had requested a starting transition window,
// well there is no point now.
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow");
startingData = null;
- } else if (windows.size() == 1 && startingView != null) {
+ } else if (mChildren.size() == 1 && startingView != null) {
// If this is the last window except for a starting transition window,
// we need to get rid of the starting transition.
mService.scheduleRemoveStartingWindowLocked(this);
@@ -602,14 +567,8 @@
}
void removeDeadWindows() {
- for (int winNdx = windows.size() - 1; winNdx >= 0;
- // WindowState#removeIfPossible() at bottom of loop may remove multiple entries from
- // windows if the window to be removed has child windows. It also may
- // not remove any windows from windows at all if win is exiting and
- // currently animating away. This ensures that winNdx is monotonically decreasing
- // and never beyond windows bounds.
- winNdx = Math.min(winNdx - 1, windows.size() - 1)) {
- WindowState win = windows.get(winNdx);
+ for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
+ WindowState win = (WindowState) mChildren.get(winNdx);
if (win.mAppDied) {
if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
"removeDeadWindows: " + win);
@@ -622,10 +581,10 @@
}
boolean hasWindowsAlive() {
- for (int i = windows.size() - 1; i >= 0; i--) {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
// No need to loop through child windows as the answer should be the same as that of the
// parent window.
- if (!windows.get(i).mAppDied) {
+ if (!((WindowState) mChildren.get(i)).mAppDied) {
return true;
}
}
@@ -636,8 +595,8 @@
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
"Marking app token " + this + " with replacing windows.");
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
w.setWillReplaceWindow(animate);
}
if (animate) {
@@ -653,8 +612,8 @@
void setWillReplaceChildWindows() {
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
+ " with replacing child windows.");
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
w.setWillReplaceChildWindows();
}
}
@@ -663,15 +622,15 @@
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
"Resetting app token " + this + " of replacing window marks.");
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
w.clearWillReplaceWindow();
}
}
void requestUpdateWallpaperIfNeeded() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState w = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = (WindowState) mChildren.get(i);
w.requestUpdateWallpaperIfNeeded();
}
}
@@ -711,8 +670,8 @@
super.addWindow(w);
boolean gotReplacementWindow = false;
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState candidate = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState candidate = (WindowState) mChildren.get(i);
gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
}
@@ -723,8 +682,8 @@
}
boolean waitingForReplacement() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState candidate = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState candidate = (WindowState) mChildren.get(i);
if (candidate.waitingForReplacement()) {
return true;
}
@@ -733,8 +692,8 @@
}
void onWindowReplacementTimeout() {
- for (int i = windows.size() - 1; i >= 0; --i) {
- windows.get(i).onWindowReplacementTimeout();
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ ((WindowState) mChildren.get(i)).onWindowReplacementTimeout();
}
}
@@ -774,8 +733,8 @@
if (!mFrozenMergedConfig.isEmpty()) {
mFrozenMergedConfig.remove();
}
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState win = (WindowState) mChildren.get(i);
win.onUnfreezeBounds();
}
mService.mWindowPlacerLocked.performSurfacePlacement();
@@ -824,80 +783,23 @@
}
void resetJustMovedInStack() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- windows.get(i).resetJustMovedInStack();
- }
- }
-
- void setWaitingForDrawnIfResizingChanged() {
- for (int i = windows.size() - 1; i >= 0; --i) {
- final WindowState win = windows.get(i);
- win.setWaitingForDrawnIfResizingChanged();
- }
- }
-
- void resizeWindows() {
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- win.addToResizingList();
- }
- }
-
- void setMovedByResize() {
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- win.setMovedByResize();
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ ((WindowState) mChildren.get(i)).resetJustMovedInStack();
}
}
void notifyMovedInStack() {
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
+ for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = (WindowState) mChildren.get(winNdx);
win.notifyMovedInStack();
}
}
- void resetDragResizingChangeReported() {
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = windows.get(winNdx);
- win.resetDragResizingChangeReported();
- }
- }
-
- void detachDisplay() {
- boolean doAnotherLayoutPass = false;
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- // We are in the middle of changing the state of displays/stacks/tasks. We need
- // to finish that, before we let layout interfere with it.
- // Also removes child windows.
- windows.get(winNdx).removeIfPossible();
- doAnotherLayoutPass = true;
- }
- if (doAnotherLayoutPass) {
- mService.mWindowPlacerLocked.requestTraversal();
- }
- }
-
- void forceWindowsScaleableInTransaction(boolean force) {
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- windows.get(winNdx).forceWindowsScaleableInTransaction(force);
- }
- }
-
- boolean isAnimating() {
- for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
- if (windows.get(winNdx).isAnimating()) {
- return true;
- }
- }
- return false;
- }
-
void setAppLayoutChanges(int changes, String reason, int displayId) {
final WindowAnimator windowAnimator = mAppAnimator.mAnimator;
- for (int i = windows.size() - 1; i >= 0; i--) {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
// Child windows will be on the same display as their parents.
- if (displayId == windows.get(i).getDisplayId()) {
+ if (displayId == ((WindowState) mChildren.get(i)).getDisplayId()) {
windowAnimator.setPendingLayoutChanges(displayId, changes);
if (DEBUG_LAYOUT_REPEATS) {
mService.mWindowPlacerLocked.debugLayoutRepeats(
@@ -909,8 +811,8 @@
}
void removeReplacedWindowIfNeeded(WindowState replacement) {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState win = (WindowState) mChildren.get(i);
if (win.removeReplacedWindowIfNeeded(replacement)) {
return;
}
@@ -932,9 +834,9 @@
mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
}
}
- final int count = windows.size();
+ final int count = mChildren.size();
for (int i = 0; i < count; i++) {
- final WindowState w = windows.get(i);
+ final WindowState w = (WindowState) mChildren.get(i);
w.onStartFreezingScreen();
}
}
@@ -945,10 +847,10 @@
return;
}
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
- final int count = windows.size();
+ final int count = mChildren.size();
boolean unfrozeWindows = false;
for (int i = 0; i < count; i++) {
- final WindowState w = windows.get(i);
+ final WindowState w = (WindowState) mChildren.get(i);
unfrozeWindows |= w.onStopFreezingScreen();
}
if (force || unfrozeWindows) {
@@ -1065,16 +967,16 @@
}
boolean isLastWindow(WindowState win) {
- return windows.size() == 1 && windows.get(0) == win;
+ return mChildren.size() == 1 && mChildren.get(0) == win;
}
void setAllAppWinAnimators() {
final ArrayList<WindowStateAnimator> allAppWinAnimators = mAppAnimator.mAllAppWinAnimators;
allAppWinAnimators.clear();
- final int windowsCount = windows.size();
+ final int windowsCount = mChildren.size();
for (int j = 0; j < windowsCount; j++) {
- windows.get(j).addWinAnimatorToList(allAppWinAnimators);
+ ((WindowState) mChildren.get(j)).addWinAnimatorToList(allAppWinAnimators);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 26be088..990405a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -624,7 +624,7 @@
*/
TaskStack getDockedStackLocked() {
final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
- return (stack != null && stack.isVisibleLocked()) ? stack : null;
+ return (stack != null && stack.isVisible()) ? stack : null;
}
/**
@@ -633,7 +633,7 @@
*/
TaskStack getDockedStackVisibleForUserLocked() {
final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
- return (stack != null && stack.isVisibleLocked(true /* ignoreKeyguard */)) ? stack : null;
+ return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null;
}
/**
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index cd576734..de8e5ac 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -541,7 +541,7 @@
final ArrayList<Task> homeStackTasks = homeStack.getTasks();
final Task topHomeStackTask = homeStackTasks.get(homeStackTasks.size() - 1);
final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
- final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisibleLocked())
+ final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisible())
|| (homeStackTasks.size() > 1 && topHomeStackTask != homeTask);
// If the home task is an on-top launcher, we don't want to minimize the docked stack.
// Instead we want everything underneath that was visible to remain visible.
@@ -639,7 +639,7 @@
final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i);
- if (stack.isVisibleLocked() && stack.isAdjustedForIme()) {
+ if (stack.isVisible() && stack.isAdjustedForIme()) {
stack.beginImeAdjustAnimation();
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3451333..4241b32 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -304,9 +304,9 @@
return false;
}
if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
- resizeWindows();
+ onResize();
} else {
- setMovedByResize();
+ onMovedByResize();
}
return true;
}
@@ -469,14 +469,14 @@
}
}
- void resetDragResizingChangeReported() {
+ private void resetDragResizingChangeReported() {
for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
mAppTokens.get(activityNdx).resetDragResizingChangeReported();
}
}
boolean isDragResizing() {
- return mDragResizing || (mStack != null && mStack.isDragResizing());
+ return mDragResizing;
}
int getDragResizeMode() {
@@ -493,10 +493,12 @@
}
}
- void detachDisplay() {
+ boolean detachFromDisplay() {
+ boolean didSomething = false;
for (int i = mAppTokens.size() - 1; i >= 0; --i) {
- mAppTokens.get(i).detachDisplay();
+ didSomething |= mAppTokens.get(i).detachFromDisplay();
}
+ return didSomething;
}
void updateDisplayInfo(final DisplayContent displayContent) {
@@ -534,15 +536,15 @@
}
}
- void resizeWindows() {
+ private void onResize() {
for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
- mAppTokens.get(activityNdx).resizeWindows();
+ mAppTokens.get(activityNdx).onResize();
}
}
- void setMovedByResize() {
+ private void onMovedByResize() {
for (int i = mAppTokens.size() - 1; i >= 0; --i) {
- mAppTokens.get(i).setMovedByResize();
+ mAppTokens.get(i).onMovedByResize();
}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 254a0d3..21fc08b 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -113,9 +113,6 @@
/** Detach this stack from its display when animation completes. */
boolean mDeferDetach;
- // Whether the stack and all its tasks is currently being drag-resized
- private boolean mDragResizing;
-
private final Rect mTmpAdjustedBounds = new Rect();
private boolean mAdjustedForIme;
private boolean mImeGoingAway;
@@ -656,7 +653,7 @@
throw new IllegalStateException(
"Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
}
- if (!ignoreVisibility && !dockedStack.isVisibleLocked()) {
+ if (!ignoreVisibility && !dockedStack.isVisible()) {
// The docked stack is being dismissed, but we caught before it finished being
// dismissed. In that case we want to treat it as if it is not occupying any space and
// let others occupy the whole display.
@@ -762,14 +759,16 @@
1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
}
- void detachDisplay() {
+ boolean detachFromDisplay() {
EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
+ boolean didSomething = false;
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- mTasks.get(taskNdx).detachDisplay();
+ didSomething |= mTasks.get(taskNdx).detachFromDisplay();
}
close();
+ return didSomething;
}
void resetAnimationBackgroundAnimator() {
@@ -846,7 +845,7 @@
mAdjustImeAmount = adjustAmount;
mAdjustDividerAmount = adjustDividerAmount;
updateAdjustedBounds();
- return isVisibleLocked(true /* ignoreKeyguard */);
+ return isVisible(true /* ignoreKeyguard */);
} else {
return false;
}
@@ -882,7 +881,7 @@
if (minimizeAmount != mMinimizeAmount) {
mMinimizeAmount = minimizeAmount;
updateAdjustedBounds();
- return isVisibleLocked(true /* ignoreKeyguard*/);
+ return isVisible(true /* ignoreKeyguard */);
} else {
return false;
}
@@ -1188,11 +1187,11 @@
}
}
- boolean isVisibleLocked() {
- return isVisibleLocked(false /* ignoreKeyguard */);
+ boolean isVisible() {
+ return isVisible(false /* ignoreKeyguard */);
}
- boolean isVisibleLocked(boolean ignoreKeyguard) {
+ boolean isVisible(boolean ignoreKeyguard) {
final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded()
&& !mService.mAnimator.mKeyguardGoingAway;
if (!ignoreKeyguard && keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
@@ -1212,20 +1211,6 @@
return false;
}
- boolean isDragResizing() {
- return mDragResizing;
- }
-
- void setDragResizingLocked(boolean resizing) {
- if (mDragResizing == resizing) {
- return;
- }
- mDragResizing = resizing;
- for (int i = mTasks.size() - 1; i >= 0 ; i--) {
- mTasks.get(i).resetDragResizingChangeReported();
- }
- }
-
@Override // AnimatesBounds
public boolean setSize(Rect bounds) {
synchronized (mService.mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index fc4fdfa..fd6994c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -92,6 +92,84 @@
return false;
}
+ void setWaitingForDrawnIfResizingChanged() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ wc.setWaitingForDrawnIfResizingChanged();
+ }
+ }
+
+ void onResize() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ wc.onResize();
+ }
+ }
+
+ void onMovedByResize() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ wc.onMovedByResize();
+ }
+ }
+
+ void resetDragResizingChangeReported() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ wc.resetDragResizingChangeReported();
+ }
+ }
+
+ boolean detachFromDisplay() {
+ boolean didSomething = false;
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ didSomething |= wc.detachFromDisplay();
+ }
+ return didSomething;
+ }
+
+ void forceWindowsScaleableInTransaction(boolean force) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ wc.forceWindowsScaleableInTransaction(force);
+ }
+ }
+
+ boolean isAnimating() {
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ final WindowContainer wc = mChildren.get(j);
+ if (wc.isAnimating()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void sendAppVisibilityToClients() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ wc.sendAppVisibilityToClients();
+ }
+ }
+
+ void setVisibleBeforeClientHidden() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ wc.setVisibleBeforeClientHidden();
+ }
+ }
+
+ boolean isVisible() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mChildren.get(i);
+ if (wc.isVisible()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/** Returns the top child container or this container if there are no children. */
WindowContainer getTop() {
return mChildren.isEmpty() ? this : mChildren.peekLast();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d4750e7..851f8d8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4011,7 +4011,7 @@
boolean isStackVisibleLocked(int stackId) {
final TaskStack stack = mStackIdToStack.get(stackId);
- return (stack != null && stack.isVisibleLocked());
+ return (stack != null && stack.isVisible());
}
public void setDockedStackCreateState(int mode, Rect bounds) {
@@ -4081,7 +4081,9 @@
void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
displayContent.detachStack(stack);
- stack.detachDisplay();
+ if (stack.detachFromDisplay()) {
+ mWindowPlacerLocked.requestTraversal();
+ }
if (stack.mStackId == DOCKED_STACK_ID) {
getDefaultDisplayContentLocked().mDividerControllerLocked
.notifyDockedStackExistsChanged(false);
@@ -4225,7 +4227,7 @@
+ " not found.");
}
if (stack.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
- && stack.isVisibleLocked()) {
+ && stack.isVisible()) {
stack.getDisplayContent().layoutNeeded = true;
mWindowPlacerLocked.performSurfacePlacement();
}
@@ -6792,7 +6794,7 @@
for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i);
final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
- if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) {
+ if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
} else {
stack.resetAdjustedForIme(false);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index dea06a9..2c359fc 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1172,6 +1172,7 @@
// TODO: Sigh...another is visible method...tried to consolidate with other isVisible methods
// below, but failed. Need to figure-out a good way to handle this long term...
+ @Override
boolean isVisible() {
// If we're animating with a saved surface, we're already visible.
// Return true so that the alpha doesn't get cleared.
@@ -1181,13 +1182,7 @@
return true;
}
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- if (c.isVisible()) {
- return true;
- }
- }
- return false;
+ return super.isVisible();
}
/**
@@ -1427,14 +1422,11 @@
&& (mAppToken == null || mAppToken.mAppAnimator.animation == null);
}
- void setMovedByResize() {
- if (DEBUG_RESIZE) Slog.d(TAG, "setMovedByResize: Moving " + this);
+ @Override
+ void onMovedByResize() {
+ if (DEBUG_RESIZE) Slog.d(TAG, "onMovedByResize: Moving " + this);
mMovedByResize = true;
-
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- c.setMovedByResize();
- }
+ super.onMovedByResize();
}
boolean onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) {
@@ -1499,14 +1491,15 @@
return changed;
}
- void addToResizingList() {
+ @Override
+ void onResize() {
// Some windows won't go through the resizing process, if they don't have a surface, so
// destroy all saved surfaces here.
destroySavedSurface();
final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
if (mHasSurface && !resizingWindows.contains(this)) {
- if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + this);
+ if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this);
resizingWindows.add(this);
// If we are not drag resizing, force recreating of a new surface so updating
@@ -1529,10 +1522,7 @@
mResizedWhileGone = true;
}
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- c.addToResizingList();
- }
+ super.onResize();
}
void onUnfreezeBounds() {
@@ -1618,15 +1608,13 @@
}
}
+ @Override
void forceWindowsScaleableInTransaction(boolean force) {
if (mWinAnimator != null && mWinAnimator.hasSurface()) {
mWinAnimator.mSurfaceController.forceScaleableInTransaction(force);
}
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- c.forceWindowsScaleableInTransaction(force);
- }
+ super.forceWindowsScaleableInTransaction(force);
}
@Override
@@ -1815,6 +1803,15 @@
Binder.restoreCallingIdentity(origId);
}
+ @Override
+ boolean detachFromDisplay() {
+ // We are in the middle of changing the state of displays/stacks/tasks. We need
+ // to finish that, before we let layout interfere with it.
+ // Also removes child windows.
+ removeIfPossible();
+ return true;
+ }
+
private void setupWindowForRemoveOnExit() {
mRemoveOnExit = true;
setDisplayLayoutNeeded();
@@ -2376,17 +2373,12 @@
return mAnimatingWithSavedSurface;
}
+ @Override
boolean isAnimating() {
if (mWinAnimator.isAnimationSet() || mAnimatingExit) {
return true;
}
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- if (c.isAnimating()) {
- return true;
- }
- }
- return false;
+ return super.isAnimating();
}
boolean isAnimatingInvisibleWithSavedSurface() {
@@ -2440,12 +2432,10 @@
}
}
- void sendAppVisibilityToClients(boolean clientHidden) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- c.sendAppVisibilityToClients(clientHidden);
- }
+ void sendAppVisibilityToClients() {
+ super.sendAppVisibilityToClients();
+ final boolean clientHidden = mAppToken.clientHidden;
if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
// Don't hide the starting window.
return;
@@ -2463,10 +2453,7 @@
mWasVisibleBeforeClientHidden |=
(mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface);
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- c.setVisibleBeforeClientHidden();
- }
+ super.setVisibleBeforeClientHidden();
}
public void clearWasVisibleBeforeClientHidden() {
@@ -3028,14 +3015,12 @@
return mDragResizing != computeDragResizing();
}
+ @Override
void setWaitingForDrawnIfResizingChanged() {
if (isDragResizeChanged()) {
mService.mWaitingForDrawn.add(this);
}
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- c.setWaitingForDrawnIfResizingChanged();
- }
+ super.setWaitingForDrawnIfResizingChanged();
}
/**
@@ -3048,12 +3033,10 @@
/**
* Resets the state whether we reported a drag resize change to the app.
*/
+ @Override
void resetDragResizingChangeReported() {
mDragResizingChangeReported = false;
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowState c = (WindowState) mChildren.get(i);
- c.resetDragResizingChangeReported();
- }
+ super.resetDragResizingChangeReported();
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 553b056..5f9bb9a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -42,12 +42,11 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
/**
- * Container of a set of related windows in the window manager. Often this
- * is an AppWindowToken, which is the handle for an Activity that it uses
- * to display windows. For nested windows, there is a WindowToken created for
- * the parent window to manage its children.
+ * Container of a set of related windows in the window manager. Often this is an AppWindowToken,
+ * which is the handle for an Activity that it uses to display windows. For nested windows, there is
+ * a WindowToken created for the parent window to manage its children.
*/
-class WindowToken {
+class WindowToken extends WindowContainer {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
// The window manager!
@@ -66,9 +65,6 @@
// For printing.
String stringName;
- // All of the windows associated with this token.
- protected final WindowList windows = new WindowList();
-
// Is key dispatching paused for this token?
boolean paused = false;
@@ -95,12 +91,12 @@
}
void removeAllWindows() {
- for (int i = windows.size() - 1; i >= 0; --i) {
- final WindowState win = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowState win = (WindowState) mChildren.get(i);
if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM, "removeAllWindows: removing win=" + win);
win.removeIfPossible();
}
- windows.clear();
+ mChildren.clear();
}
void setExiting() {
@@ -108,13 +104,13 @@
return;
}
- final int count = windows.size();
+ final int count = mChildren.size();
boolean changed = false;
boolean delayed = false;
DisplayContent displayContent = null;
for (int i = 0; i < count; i++) {
- final WindowState win = windows.get(i);
+ final WindowState win = (WindowState) mChildren.get(i);
if (win.mWinAnimator.isAnimationSet()) {
delayed = true;
// TODO: This is technically wrong as a token can have windows on multi-displays
@@ -138,8 +134,8 @@
int adjustAnimLayer(int adj) {
int highestAnimLayer = -1;
- for (int j = windows.size() - 1; j >= 0; j--) {
- final WindowState w = windows.get(j);
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ final WindowState w = (WindowState) mChildren.get(j);
final int winHighestAnimLayer = w.adjustAnimLayer(adj);
if (winHighestAnimLayer > highestAnimLayer) {
highestAnimLayer = winHighestAnimLayer;
@@ -151,11 +147,12 @@
return highestAnimLayer;
}
- private WindowState getTopWindow() {
- if (windows.isEmpty()) {
+ /* package level access for test. */
+ WindowState getTopWindow() {
+ if (mChildren.isEmpty()) {
return null;
}
- return (WindowState) windows.get(windows.size() - 1).getTop();
+ return (WindowState) mChildren.get(mChildren.size() - 1).getTop();
}
/**
@@ -163,9 +160,10 @@
* @param target The window to search for.
* @return The index of win in windows or of the window that is an ancestor of win.
*/
- private int getWindowIndex(WindowState target) {
- for (int i = windows.size() - 1; i >= 0; --i) {
- final WindowState w = windows.get(i);
+ /* package level access for test. */
+ int getWindowIndex(WindowState target) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowState w = (WindowState) mChildren.get(i);
if (w == target || w.hasChild(target)) {
return i;
}
@@ -250,9 +248,9 @@
} else {
win.addNonAppWindowToList();
}
- if (!windows.contains(win)) {
+ if (!mChildren.contains(win)) {
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
- windows.add(tokenWindowsPos, win);
+ mChildren.add(tokenWindowsPos, win);
}
} else {
addChildWindow(win);
@@ -424,9 +422,9 @@
}
int reAddAppWindows(DisplayContent displayContent, int index) {
- final int count = windows.size();
+ final int count = mChildren.size();
for (int i = 0; i < count; i++) {
- final WindowState win = windows.get(i);
+ final WindowState win = (WindowState) mChildren.get(i);
final DisplayContent winDisplayContent = win.getDisplayContent();
if (winDisplayContent == displayContent || winDisplayContent == null) {
win.mDisplayContent = displayContent;
@@ -441,9 +439,9 @@
* ordering the windows in mWindows
*/
private int findIdxBasedOnAppTokens(WindowState win) {
- WindowList windows = win.getWindowList();
+ final WindowList windows = win.getWindowList();
for(int j = windows.size() - 1; j >= 0; j--) {
- WindowState wentry = windows.get(j);
+ final WindowState wentry = windows.get(j);
if(wentry.mAppToken == win.mAppToken) {
return j;
}
@@ -453,10 +451,10 @@
/** Return the first window in the token window list that isn't a starting window or null. */
WindowState getFirstNonStartingWindow() {
- final int count = windows.size();
+ 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 = windows.get(i);
+ final WindowState w = (WindowState) mChildren.get(i);
if (w.mAttrs.type != TYPE_APPLICATION_STARTING) {
return w;
}
@@ -466,17 +464,17 @@
@CallSuper
void removeWindow(WindowState win) {
- windows.remove(win);
+ mChildren.remove(win);
}
/** Returns true if the token windows list is empty. */
boolean isEmpty() {
- return windows.isEmpty();
+ return mChildren.isEmpty();
}
WindowState getReplacingWindow() {
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState win = (WindowState) mChildren.get(i);
final WindowState replacing = win.getReplacingWindow();
if (replacing != null) {
return replacing;
@@ -486,8 +484,8 @@
}
void hideWallpaperToken(boolean wasDeferred, String reason) {
- for (int j = windows.size() - 1; j >= 0; j--) {
- final WindowState wallpaper = windows.get(j);
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ final WindowState wallpaper = (WindowState) mChildren.get(j);
wallpaper.hideWallpaperWindow(wasDeferred, reason);
}
hidden = true;
@@ -495,8 +493,8 @@
void sendWindowWallpaperCommand(
String action, int x, int y, int z, Bundle extras, boolean sync) {
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = windows.get(wallpaperNdx);
+ for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
try {
wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
// We only want to be synchronous with one wallpaper.
@@ -508,8 +506,8 @@
void updateWallpaperOffset(int dw, int dh, boolean sync) {
final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = windows.get(wallpaperNdx);
+ for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
winAnimator.computeShownFrameLocked();
@@ -529,8 +527,8 @@
}
final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- WindowState wallpaper = windows.get(wallpaperNdx);
+ for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
if (visible) {
wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
}
@@ -552,8 +550,8 @@
}
final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
- for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
- final WindowState wallpaper = windows.get(wallpaperNdx);
+ for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
if (visible) {
wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
@@ -628,8 +626,8 @@
}
boolean hasVisibleNotDrawnWallpaper() {
- for (int j = windows.size() - 1; j >= 0; --j) {
- final WindowState wallpaper = windows.get(j);
+ for (int j = mChildren.size() - 1; j >= 0; --j) {
+ final WindowState wallpaper = (WindowState) mChildren.get(j);
if (wallpaper.hasVisibleNotDrawnWallpaper()) {
return true;
}
@@ -639,8 +637,8 @@
int getHighestAnimLayer() {
int highest = -1;
- for (int j = 0; j < windows.size(); j++) {
- final WindowState w = windows.get(j);
+ for (int j = 0; j < mChildren.size(); j++) {
+ final WindowState w = (WindowState) mChildren.get(j);
final int wLayer = w.getHighestAnimLayer();
if (wLayer > highest) {
highest = wLayer;
@@ -656,7 +654,7 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("windows="); pw.println(windows);
+ pw.print(prefix); pw.print("windows="); pw.println(mChildren);
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
pw.print(" hidden="); pw.print(hidden);
pw.print(" hasVisible="); pw.println(hasVisible);
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
new file mode 100644
index 0000000..4050795
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 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.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.IWindow;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
+/**
+ * Tests for the {@link WindowState} class.
+ *
+ * Build: mmma -j32 frameworks/base/services/tests/servicestests
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Run: adb shell am instrument -w -e class com.android.server.wm.AppWindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+public class AppWindowTokenTests extends AndroidTestCase {
+
+ private static WindowManagerService sWm = null;
+ private final WindowManagerPolicy mPolicy = new TestWindowManagerPolicy();
+ private final IWindow mIWindow = new TestIWindow();
+
+ @Override
+ public void setUp() throws Exception {
+ final Context context = getContext();
+ if (sWm == null) {
+ // We only want to do this once for the test process as we don't want WM to try to
+ // register a bunch of local services again.
+ sWm = WindowManagerService.main(context, null, true, false, false, mPolicy);
+ }
+ }
+
+ public void testFindMainWindow() throws Exception {
+ final TestAppWindowToken token = new TestAppWindowToken();
+
+ assertNull(token.findMainWindow());
+
+ final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token);
+ final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ token.addWindow(window1);
+ assertEquals(window1, token.findMainWindow());
+ window1.mAnimatingExit = true;
+ assertEquals(window1, token.findMainWindow());
+ final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token);
+ token.addWindow(window2);
+ assertEquals(window2, token.findMainWindow());
+ }
+
+ private WindowState createWindow(WindowState parent, int type, WindowToken token) {
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
+
+ return new WindowState(sWm, null, mIWindow, token, parent, 0, 0, attrs, 0,
+ sWm.getDefaultDisplayContentLocked(), 0);
+ }
+
+ /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
+ private class TestAppWindowToken extends AppWindowToken {
+
+ TestAppWindowToken() {
+ super(sWm, null, false);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index bd7c0b3..ea8b7bb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -20,33 +20,35 @@
import android.test.suitebuilder.annotation.SmallTest;
import java.util.Comparator;
+import java.util.LinkedList;
/**
* Test class for {@link WindowContainer}.
*
* Build: mmma -j32 frameworks/base/services/tests/servicestests
- * Install: adb install -r out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
* Run: adb shell am instrument -w -e class com.android.server.wm.WindowContainerTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
*/
@SmallTest
public class WindowContainerTests extends AndroidTestCase {
public void testCreation() throws Exception {
- final TestWindowContainer w = new TestWindowContainer();
+ final TestWindowContainer w = new TestWindowContainerBuilder().setLayer(0).build();
assertNull("window must have no parent", w.getParentWindow());
assertEquals("window must have no children", 0, w.getChildrenCount());
}
public void testAdd() throws Exception {
- final TestWindowContainer root = new TestWindowContainer();
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.setLayer(0).build();
- final TestWindowContainer layer1 = root.addChildWindow(1);
- final TestWindowContainer secondLayer1 = root.addChildWindow(1);
- final TestWindowContainer layer2 = root.addChildWindow(2);
- final TestWindowContainer layerNeg1 = root.addChildWindow(-1);
- final TestWindowContainer layerNeg2 = root.addChildWindow(-2);
- final TestWindowContainer secondLayerNeg1 = root.addChildWindow(-1);
- final TestWindowContainer layer0 = root.addChildWindow(0);
+ final TestWindowContainer layer1 = root.addChildWindow(builder.setLayer(1));
+ final TestWindowContainer secondLayer1 = root.addChildWindow(builder.setLayer(1));
+ final TestWindowContainer layer2 = root.addChildWindow(builder.setLayer(2));
+ final TestWindowContainer layerNeg1 = root.addChildWindow(builder.setLayer(-1));
+ final TestWindowContainer layerNeg2 = root.addChildWindow(builder.setLayer(-2));
+ final TestWindowContainer secondLayerNeg1 = root.addChildWindow(builder.setLayer(-1));
+ final TestWindowContainer layer0 = root.addChildWindow(builder.setLayer(0));
assertEquals(7, root.getChildrenCount());
@@ -68,13 +70,14 @@
}
public void testHasChild() throws Exception {
- final TestWindowContainer root = new TestWindowContainer();
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.setLayer(0).build();
- final TestWindowContainer child1 = root.addChildWindow(1);
- final TestWindowContainer child2 = root.addChildWindow(1);
- final TestWindowContainer child11 = child1.addChildWindow(1);
- final TestWindowContainer child12 = child1.addChildWindow(1);
- final TestWindowContainer child21 = child2.addChildWindow(1);
+ final TestWindowContainer child1 = root.addChildWindow();
+ final TestWindowContainer child2 = root.addChildWindow();
+ final TestWindowContainer child11 = child1.addChildWindow();
+ final TestWindowContainer child12 = child1.addChildWindow();
+ final TestWindowContainer child21 = child2.addChildWindow();
assertEquals(2, root.getChildrenCount());
assertEquals(2, child1.getChildrenCount());
@@ -96,13 +99,14 @@
}
public void testRemove() throws Exception {
- final TestWindowContainer root = new TestWindowContainer();
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.setLayer(0).build();
- final TestWindowContainer child1 = root.addChildWindow(1);
- final TestWindowContainer child2 = root.addChildWindow(1);
- final TestWindowContainer child11 = child1.addChildWindow(1);
- final TestWindowContainer child12 = child1.addChildWindow(1);
- final TestWindowContainer child21 = child2.addChildWindow(1);
+ final TestWindowContainer child1 = root.addChildWindow();
+ final TestWindowContainer child2 = root.addChildWindow();
+ final TestWindowContainer child11 = child1.addChildWindow();
+ final TestWindowContainer child12 = child1.addChildWindow();
+ final TestWindowContainer child21 = child2.addChildWindow();
child12.remove();
assertNull(child12.getParentWindow());
@@ -125,9 +129,67 @@
assertEquals(0, root.getChildrenCount());
}
+ public void testDetachFromDisplay() throws Exception {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.setLayer(0).build();
+
+ final TestWindowContainer child1 = root.addChildWindow(builder.setCanDetach(true));
+ final TestWindowContainer child2 = root.addChildWindow();
+ final TestWindowContainer child11 = child1.addChildWindow();
+ final TestWindowContainer child12 = child1.addChildWindow(builder.setCanDetach(true));
+ final TestWindowContainer child21 = child2.addChildWindow();
+
+ assertTrue(root.detachFromDisplay());
+ assertTrue(child1.detachFromDisplay());
+ assertFalse(child11.detachFromDisplay());
+ assertTrue(child12.detachFromDisplay());
+ assertFalse(child2.detachFromDisplay());
+ assertFalse(child21.detachFromDisplay());
+ }
+
+ public void testIsAnimating() throws Exception {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.setLayer(0).build();
+
+ final TestWindowContainer child1 = root.addChildWindow(builder.setIsAnimating(true));
+ final TestWindowContainer child2 = root.addChildWindow();
+ final TestWindowContainer child11 = child1.addChildWindow();
+ final TestWindowContainer child12 = child1.addChildWindow(builder.setIsAnimating(true));
+ final TestWindowContainer child21 = child2.addChildWindow();
+
+ assertTrue(root.isAnimating());
+ assertTrue(child1.isAnimating());
+ assertFalse(child11.isAnimating());
+ assertTrue(child12.isAnimating());
+ assertFalse(child2.isAnimating());
+ assertFalse(child21.isAnimating());
+ }
+
+ public void testIsVisible() throws Exception {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.setLayer(0).build();
+
+ final TestWindowContainer child1 = root.addChildWindow(builder.setIsVisible(true));
+ final TestWindowContainer child2 = root.addChildWindow();
+ final TestWindowContainer child11 = child1.addChildWindow();
+ final TestWindowContainer child12 = child1.addChildWindow(builder.setIsVisible(true));
+ final TestWindowContainer child21 = child2.addChildWindow();
+
+ assertTrue(root.isVisible());
+ assertTrue(child1.isVisible());
+ assertFalse(child11.isVisible());
+ assertTrue(child12.isVisible());
+ assertFalse(child2.isVisible());
+ assertFalse(child21.isVisible());
+ }
+
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private class TestWindowContainer extends WindowContainer {
private final int mLayer;
+ private final LinkedList<String> mUsers = new LinkedList();
+ private final boolean mCanDetach;
+ private boolean mIsAnimating;
+ private boolean mIsVisible;
/**
* Compares 2 window layers and returns -1 if the first is lesser than the second in terms
@@ -145,12 +207,13 @@
return 1;
};
- TestWindowContainer() {
- mLayer = 0;
- }
-
- TestWindowContainer(int layer) {
+ TestWindowContainer(int layer, LinkedList<String> users, boolean canDetach,
+ boolean isAnimating, boolean isVisible) {
mLayer = layer;
+ mUsers.addAll(users);
+ mCanDetach = canDetach;
+ mIsAnimating = isAnimating;
+ mIsVisible = isVisible;
}
TestWindowContainer getParentWindow() {
@@ -161,15 +224,79 @@
return mChildren.size();
}
- TestWindowContainer addChildWindow(int layer) {
- TestWindowContainer child = new TestWindowContainer(layer);
+ TestWindowContainer addChildWindow(TestWindowContainerBuilder childBuilder) {
+ TestWindowContainer child = childBuilder.build();
addChild(child, mWindowSubLayerComparator);
return child;
}
+ TestWindowContainer addChildWindow() {
+ return addChildWindow(new TestWindowContainerBuilder().setLayer(1));
+ }
+
TestWindowContainer getChildAt(int index) {
return (TestWindowContainer) mChildren.get(index);
}
+
+ @Override
+ boolean detachFromDisplay() {
+ return super.detachFromDisplay() || mCanDetach;
+ }
+
+ @Override
+ boolean isAnimating() {
+ return mIsAnimating || super.isAnimating();
+ }
+
+ @Override
+ boolean isVisible() {
+ return mIsVisible || super.isVisible();
+ }
}
+ private class TestWindowContainerBuilder {
+ private int mLayer;
+ private LinkedList<String> mUsers = new LinkedList();
+ private boolean mCanDetach;
+ private boolean mIsAnimating;
+ private boolean mIsVisible;
+
+ TestWindowContainerBuilder setLayer(int layer) {
+ mLayer = layer;
+ return this;
+ }
+
+ TestWindowContainerBuilder addUser(String user) {
+ mUsers.add(user);
+ return this;
+ }
+
+ TestWindowContainerBuilder setCanDetach(boolean canDetach) {
+ mCanDetach = canDetach;
+ return this;
+ }
+
+ TestWindowContainerBuilder setIsAnimating(boolean isAnimating) {
+ mIsAnimating = isAnimating;
+ return this;
+ }
+
+ TestWindowContainerBuilder setIsVisible(boolean isVisible) {
+ mIsVisible = isVisible;
+ return this;
+ }
+
+ TestWindowContainerBuilder reset() {
+ mLayer = 0;
+ mUsers.clear();
+ mCanDetach = false;
+ mIsAnimating = false;
+ mIsVisible = false;
+ return this;
+ }
+
+ TestWindowContainer build() {
+ return new TestWindowContainer(mLayer, mUsers, mCanDetach, mIsAnimating, mIsVisible);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 64de15d..c55cfb9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -32,7 +32,7 @@
* Tests for the {@link WindowState} class.
*
* Build: mmma -j32 frameworks/base/services/tests/servicestests
- * Install: adb install -r out/target/product/angler/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
* Run: adb shell am instrument -w -e class com.android.server.wm.WindowStateTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
*/
@SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
new file mode 100644
index 0000000..b907161
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2016 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.content.Context;
+import android.os.IBinder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.IWindow;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+
+/**
+ * Tests for the {@link WindowState} class.
+ *
+ * Build: mmma -j32 frameworks/base/services/tests/servicestests
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Run: adb shell am instrument -w -e class com.android.server.wm.WindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+public class WindowTokenTests extends AndroidTestCase {
+
+ private static WindowManagerService sWm = null;
+ private final WindowManagerPolicy mPolicy = new TestWindowManagerPolicy();
+ private final IWindow mIWindow = new TestIWindow();
+
+ @Override
+ public void setUp() throws Exception {
+ final Context context = getContext();
+ if (sWm == null) {
+ // We only want to do this once for the test process as we don't want WM to try to
+ // register a bunch of local services again.
+ sWm = WindowManagerService.main(context, null, true, false, false, mPolicy);
+ }
+ }
+
+ public void testAddWindow() throws Exception {
+ final TestWindowToken token = new TestWindowToken();
+
+ assertEquals(0, token.getWindowsCount());
+
+ final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+ final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+ final WindowState window3 = createWindow(null, TYPE_APPLICATION, token);
+
+ token.addWindow(window1);
+ // NOTE: Child windows will not be added to the token as window containers can only
+ // contain/reference their direct children.
+ token.addWindow(window11);
+ token.addWindow(window12);
+ token.addWindow(window2);
+ token.addWindow(window3);
+
+ // Should not contain the child windows that were added above.
+ assertEquals(3, token.getWindowsCount());
+ assertTrue(token.hasWindow(window1));
+ assertFalse(token.hasWindow(window11));
+ assertFalse(token.hasWindow(window12));
+ assertTrue(token.hasWindow(window2));
+ assertTrue(token.hasWindow(window3));
+ }
+
+ public void testAdjustAnimLayer() throws Exception {
+ final TestWindowToken token = new TestWindowToken();
+ final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+ final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+ final WindowState window3 = createWindow(null, TYPE_APPLICATION, token);
+
+ token.addWindow(window1);
+ token.addWindow(window2);
+ token.addWindow(window3);
+
+ final int adj = 50;
+ final int window2StartLayer = window2.mLayer = 100;
+ final int window3StartLayer = window3.mLayer = 200;
+ final int highestLayer = token.adjustAnimLayer(adj);
+
+ assertEquals(adj, window1.mWinAnimator.mAnimLayer);
+ assertEquals(adj, window11.mWinAnimator.mAnimLayer);
+ assertEquals(adj, window12.mWinAnimator.mAnimLayer);
+ assertEquals(window2StartLayer + adj, window2.mWinAnimator.mAnimLayer);
+ assertEquals(window3StartLayer + adj, window3.mWinAnimator.mAnimLayer);
+ assertEquals(window3StartLayer + adj, highestLayer);
+ }
+
+ public void testGetTopWindow() throws Exception {
+ final TestWindowToken token = new TestWindowToken();
+
+ assertNull(token.getTopWindow());
+
+ final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+ token.addWindow(window1);
+ assertEquals(window1, token.getTopWindow());
+ final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ assertEquals(window12, token.getTopWindow());
+
+ final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+ token.addWindow(window2);
+ // Since new windows are added to the bottom of the token, we would still expect the
+ // previous one to the top.
+ assertEquals(window12, token.getTopWindow());
+ }
+
+ public void testGetWindowIndex() throws Exception {
+ final TestWindowToken token = new TestWindowToken();
+
+ final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+ assertEquals(-1, token.getWindowIndex(window1));
+ token.addWindow(window1);
+ assertEquals(0, token.getWindowIndex(window1));
+ final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+ // Child windows should report the same index as their parents.
+ assertEquals(0, token.getWindowIndex(window11));
+ assertEquals(0, token.getWindowIndex(window12));
+
+ final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+ assertEquals(-1, token.getWindowIndex(window2));
+ token.addWindow(window2);
+ // Since new windows are added to the bottom of the token, we would expect the added window
+ // to be at index 0.
+ assertEquals(0, token.getWindowIndex(window2));
+ assertEquals(1, token.getWindowIndex(window1));
+ }
+
+ private WindowState createWindow(WindowState parent, int type, WindowToken token) {
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
+
+ return new WindowState(sWm, null, mIWindow, token, parent, 0, 0, attrs, 0,
+ sWm.getDefaultDisplayContentLocked(), 0);
+ }
+
+ /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+ private class TestWindowToken extends WindowToken {
+
+ TestWindowToken() {
+ super(sWm, null, 0, false);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+ }
+}