diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 2365a45913105..a5d0c2ddfb206 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -1017,7 +1017,7 @@ public class AppTransition implements Dump { } private Animation createRelaunchAnimation(int appWidth, int appHeight, - Rect containingFrame) { + Rect containingFrame, Rect contentInsets) { getDefaultNextAppTransitionStartRect(mTmpFromClipRect); final int left = mTmpFromClipRect.left; final int top = mTmpFromClipRect.top; @@ -1027,7 +1027,11 @@ public class AppTransition implements Dump { float fromWidth = mTmpFromClipRect.width(); float toWidth = mTmpToClipRect.width(); float fromHeight = mTmpFromClipRect.height(); - float toHeight = mTmpToClipRect.height(); + // While the window might span the whole display, the actual content will be cropped to the + // system decoration frame, for example when the window is docked. We need to take into + // account the visible height when constructing the animation. + float toHeight = mTmpToClipRect.height() - contentInsets.top - contentInsets.bottom; + int translateAdjustment = 0; if (fromWidth <= toWidth && fromHeight <= toHeight) { // The final window is larger in both dimensions than current window (e.g. we are // maximizing), so we can simply unclip the new window and there will be no disappearing @@ -1037,12 +1041,17 @@ public class AppTransition implements Dump { // The disappearing window has one larger dimension. We need to apply scaling, so the // first frame of the entry animation matches the old window. set.addAnimation(new ScaleAnimation(fromWidth / toWidth, 1, fromHeight / toHeight, 1)); + // We might not be going exactly full screen, but instead be aligned under the status + // bar using cropping. We still need to account for the cropped part, which will also + // be scaled. + translateAdjustment = (int) (contentInsets.top * fromHeight / toHeight); } - // We might not be going exactly full screen, but instead be aligned under the status bar. - // We need to take this into account when creating the translate animation. + // We animate the translation from the old position of the removed window, to the new + // position of the added window. The latter might not be full screen, for example docked for + // docked windows. TranslateAnimation translate = new TranslateAnimation(left - containingFrame.left, - 0, top - containingFrame.top, 0); + 0, top - containingFrame.top - translateAdjustment, 0); set.addAnimation(translate); set.setDuration(DEFAULT_APP_TRANSITION_DURATION); set.setZAdjustment(Animation.ZORDER_TOP); @@ -1086,7 +1095,7 @@ public class AppTransition implements Dump { + " anim=" + a + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (transit == TRANSIT_ACTIVITY_RELAUNCH) { - a = createRelaunchAnimation(appWidth, appHeight, containingFrame); + a = createRelaunchAnimation(appWidth, appHeight, containingFrame, contentInsets); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=" + mNextAppTransition diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 05e51caba57ca..643c471086d5f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2869,6 +2869,7 @@ public class WindowManagerService extends IWindowManager.Stub Rect surfaceInsets = null; final boolean fullscreen = win != null && win.isFullscreen(width, height); final boolean freeform = win != null && win.inFreeformWorkspace(); + final boolean docked = win != null && win.inDockedWorkspace(); if (win != null) { // Containing frame will usually cover the whole screen, including dialog windows. // For freeform workspace windows it will not cover the whole screen and it also @@ -2880,10 +2881,11 @@ public class WindowManagerService extends IWindowManager.Stub containingFrame.set(win.mContainingFrame); } surfaceInsets = win.getAttrs().surfaceInsets; - if (fullscreen) { + if (fullscreen || docked) { // For fullscreen windows use the window frames and insets to set the thumbnail - // clip. For none-fullscreen windows we use the app display region so the clip - // isn't affected by the window insets. + // clip. For non-fullscreen windows we use the app display region so the clip + // isn't affected by the window insets. Docked windows are cropped to the system + // decorations, so we need tell the animation about it too. contentInsets.set(win.mContentInsets); appFrame.set(win.mFrame); } else { @@ -2899,6 +2901,15 @@ public class WindowManagerService extends IWindowManager.Stub // screen gets the enter animation. Both appear in the mOpeningApps set. enter = false; } + if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "Loading animation for app transition." + + " transit=" + AppTransition.appTransitionToString(transit) + + " enter=" + enter + + " containingWidth=" + containingWidth + + " containingHeight=" + containingHeight + + " containingFrame=" + containingFrame + + " contentInsets=" + contentInsets + + " surfaceInsets=" + surfaceInsets + + " appFrame=" + appFrame); Animation a = mAppTransition.loadAnimation(lp, transit, enter, containingWidth, containingHeight, mCurConfiguration.orientation, containingFrame, contentInsets, surfaceInsets, appFrame, isVoiceInteraction, freeform, atoken.mTask.mTaskId);