summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java8
-rw-r--r--services/core/java/com/android/server/wm/DimLayerController.java6
-rw-r--r--services/core/java/com/android/server/wm/Task.java31
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java35
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java6
5 files changed, 77 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 4ec297e31015..545b9db75ecd 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -499,7 +499,7 @@ class AppWindowToken extends WindowToken {
+ " with replacing child windows.");
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
final WindowState w = allAppWindows.get(i);
- if (w.isChildWindow()) {
+ if (w.shouldBeReplacedWithChildren()) {
w.setReplacing(false /* animate */);
}
}
@@ -539,8 +539,9 @@ class AppWindowToken extends WindowToken {
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
WindowState candidate = allAppWindows.get(i);
if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null &&
- candidate.getWindowTag().equals(w.getWindowTag().toString())) {
+ candidate.getWindowTag().toString().equals(w.getWindowTag().toString())) {
candidate.mReplacingWindow = w;
+ w.mSkipEnterAnimationForSeamlessReplacement = !candidate.mAnimateReplacingWindow;
// if we got a replacement window, reset the timeout to give drawing more time
service.mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
@@ -575,6 +576,9 @@ class AppWindowToken extends WindowToken {
continue;
}
candidate.mWillReplaceWindow = false;
+ if (candidate.mReplacingWindow != null) {
+ candidate.mReplacingWindow.mSkipEnterAnimationForSeamlessReplacement = false;
+ }
// Since the window already timed out, remove it immediately now.
// Use removeWindowInnerLocked() instead of removeWindowLocked(), as the latter
// delays removal on certain conditions, which will leave the stale window in the
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 3ec02b9f66fc..c240d0733a0a 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -169,6 +169,10 @@ class DimLayerController {
+ " dimLayerUser=" + dimLayerUser.toShortString()
+ " state.continueDimming=" + state.continueDimming
+ " state.dimLayer.isDimming=" + state.dimLayer.isDimming());
+ if (state.animator != null && state.animator.mWin.mWillReplaceWindow) {
+ return;
+ }
+
if (!state.continueDimming && state.dimLayer.isDimming()) {
state.animator = null;
dimLayerUser.getDimBounds(mTmpBounds);
@@ -303,7 +307,7 @@ class DimLayerController {
applyDim(dimLayerUser, animator, true /* aboveApp */);
}
- private void applyDim(
+ void applyDim(
DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator, boolean aboveApp) {
if (dimLayerUser == null) {
Slog.e(TAG, "Trying to apply dim layer for: " + this
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 13bfa5713a2f..46a8dffc02e6 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -27,6 +27,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import android.app.ActivityManager.StackId;
import android.content.pm.ActivityInfo;
@@ -456,6 +457,11 @@ class Task implements DimLayer.DimLayerUser {
/** Bounds of the task to be used for dimming, as well as touch related tests. */
@Override
public void getDimBounds(Rect out) {
+ final DisplayContent displayContent = mStack.getDisplayContent();
+ // It doesn't matter if we in particular are part of the resize, since we couldn't have
+ // a DimLayer anyway if we weren't visible.
+ final boolean dockedResizing = displayContent != null ?
+ displayContent.mDividerControllerLocked.isResizing() : false;
if (useCurrentBounds()) {
if (inFreeformWorkspace() && getMaxVisibleBounds(out)) {
return;
@@ -464,8 +470,16 @@ class Task implements DimLayer.DimLayerUser {
if (!mFullscreen) {
// When minimizing the docked stack when going home, we don't adjust the task bounds
// so we need to intersect the task bounds with the stack bounds here.
- mStack.getBounds(mTmpRect);
- mTmpRect.intersect(mBounds);
+ //
+ // If we are Docked Resizing with snap points, the task bounds could be smaller than the stack
+ // bounds and so we don't even want to use them. Even if the app should not be resized the Dim
+ // should keep up with the divider.
+ if (dockedResizing) {
+ mStack.getBounds(out);
+ } else {
+ mStack.getBounds(mTmpRect);
+ mTmpRect.intersect(mBounds);
+ }
out.set(mTmpRect);
} else {
out.set(mBounds);
@@ -476,7 +490,7 @@ class Task implements DimLayer.DimLayerUser {
// The bounds has been adjusted to accommodate for a docked stack, but the docked stack
// is not currently visible. Go ahead a represent it as fullscreen to the rest of the
// system.
- mStack.getDisplayContent().getLogicalDisplayRect(out);
+ displayContent.getLogicalDisplayRect(out);
}
void setDragResizing(boolean dragResizing, int dragResizeMode) {
@@ -577,7 +591,16 @@ class Task implements DimLayer.DimLayerUser {
// If we are not drag resizing, force recreating of a new surface so updating
// the content and positioning that surface will be in sync.
- if (!win.computeDragResizing()) {
+ //
+ // As we use this flag as a hint to freeze surface boundary updates,
+ // we'd like to only apply this to TYPE_BASE_APPLICATION,
+ // windows of TYPE_APPLICATION like dialogs, could appear
+ // to not be drag resizing while they resize, but we'd
+ // still like to manipulate their frame to update crop, etc...
+ //
+ // Anyway we don't need to synchronize position and content updates for these
+ // windows since they aren't at the base layer and could be moved around anyway.
+ if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION) {
win.mResizedWhileNotDragResizing = true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8371cfe7a2dd..bf697172f609 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -82,6 +82,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+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 android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -444,6 +445,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// If not null, the window that will be used to replace the old one. This is being set when
// the window is added and unset when this window reports its first draw.
WindowState mReplacingWindow = null;
+ // For the new window in the replacement transition, if we have
+ // requested to replace without animation, then we should
+ // make sure we also don't apply an enter animation for
+ // the new window.
+ boolean mSkipEnterAnimationForSeamlessReplacement = false;
// Whether this window is being moved via the resize API
boolean mMovedByResize;
@@ -1552,7 +1558,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// If app died visible, apply a dim over the window to indicate that it's inactive
mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
} else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
- && mDisplayContent != null && !mAnimatingExit && isDisplayedLw()) {
+ && mDisplayContent != null && !mAnimatingExit && isVisibleUnchecked()) {
mDisplayContent.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator);
}
}
@@ -1571,12 +1577,16 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
for (int i = mAppToken.allAppWindows.size() - 1; i >= 0; i--) {
final WindowState win = mAppToken.allAppWindows.get(i);
- if (win.mWillReplaceWindow && win.mReplacingWindow == this) {
+ if (win.mWillReplaceWindow && win.mReplacingWindow == this && hasDrawnLw()) {
if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + win);
+ if (win.isDimming()) {
+ win.transferDimToReplacement();
+ }
win.mWillReplaceWindow = false;
win.mAnimateReplacingWindow = false;
win.mReplacingRemoveRequested = false;
win.mReplacingWindow = null;
+ mSkipEnterAnimationForSeamlessReplacement = false;
if (win.mAnimatingExit) {
mService.removeWindowInnerLocked(win);
}
@@ -2710,4 +2720,25 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
return winY;
}
+
+ void transferDimToReplacement() {
+ final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
+ if (dimLayerUser != null && mDisplayContent != null) {
+ mDisplayContent.mDimLayerController.applyDim(dimLayerUser,
+ mReplacingWindow.mWinAnimator,
+ (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? true : false);
+ }
+ }
+
+ // During activity relaunch due to resize, we sometimes use window replacement
+ // for only child windows (as the main window is handled by window preservation)
+ // and the big surface.
+ //
+ // Though windows of TYPE_APPLICATION (as opposed to TYPE_BASE_APPLICATION)
+ // are not children in the sense of an attached window, we also want to replace
+ // them at such phases, as they won't be covered by window preservation,
+ // and in general we expect them to return following relaunch.
+ boolean shouldBeReplacedWithChildren() {
+ return isChildWindow() || mAttrs.type == TYPE_APPLICATION;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 06c3a0244cff..6fcc8f9db667 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1684,6 +1684,12 @@ class WindowStateAnimator {
}
void applyEnterAnimationLocked() {
+ // If we are the new part of a window replacement transition and we have requested
+ // not to animate, we instead want to make it seamless, so we don't want to apply
+ // an enter transition.
+ if (mWin.mSkipEnterAnimationForSeamlessReplacement) {
+ return;
+ }
final int transit;
if (mEnterAnimationPending) {
mEnterAnimationPending = false;