diff options
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; |