Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35a57f81 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Cleaned-up logic for determining clip rect for transitions animations.

Previous logic led to several edge cases which fixes sometimes broke
other edge cases. New logic uses the clip rect provided by the
transformation as-is and doesn't try to adjust it based on window
flags. Correct clip rect is set in
WindowManagerService#applyAnimationLock using the content insets
before the animation is loaded.

Bug: 21727851
Bug: 20652683
Bug: 19523205
Bug: 15046646
https://code.google.com/p/android/issues/detail?id=161362
Change-Id: I2d4ed6196edb8ee8c401fe9a242aec70d3494574
parent 7fe86c47
Loading
Loading
Loading
Loading
+9 −19
Original line number Diff line number Diff line
@@ -715,7 +715,7 @@ public class AppTransition implements Dump {
     */
    Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
            int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
            Rect contentInsets, boolean isFullScreen) {
            Rect contentInsets) {
        Animation a;
        final int thumbWidthI = mNextAppTransitionStartWidth;
        final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -735,9 +735,6 @@ public class AppTransition implements Dump {
                    scaledTopDecor = (int) (scale * contentInsets.top);
                    int unscaledThumbHeight = (int) (thumbHeight / scale);
                    mTmpFromClipRect.set(containingFrame);
                    if (isFullScreen) {
                        mTmpFromClipRect.top = contentInsets.top;
                    }
                    mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
                    mTmpToClipRect.set(containingFrame);
                } else {
@@ -745,15 +742,13 @@ public class AppTransition implements Dump {
                    scale = thumbHeight / (appHeight - contentInsets.top);
                    scaledTopDecor = (int) (scale * contentInsets.top);
                    int unscaledThumbWidth = (int) (thumbWidth / scale);
                    int unscaledThumbHeight = (int) (thumbHeight / scale);
                    mTmpFromClipRect.set(containingFrame);
                    if (isFullScreen) {
                        mTmpFromClipRect.top = contentInsets.top;
                        mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
                    }
                    mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
                    mTmpToClipRect.set(containingFrame);
                }
                // exclude top screen decor (status bar) region from the source clip.
                mTmpFromClipRect.top = contentInsets.top;

                mNextAppTransitionInsets.set(contentInsets);

                Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
@@ -800,24 +795,19 @@ public class AppTransition implements Dump {
                    int unscaledThumbHeight = (int) (thumbHeight / scale);
                    mTmpFromClipRect.set(containingFrame);
                    mTmpToClipRect.set(containingFrame);
                    if (isFullScreen) {
                        mTmpToClipRect.top = contentInsets.top;
                    }
                    mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
                } else {
                    // In landscape, we scale the height and clip to the top/left square
                    scale = thumbHeight / (appHeight - contentInsets.top);
                    scaledTopDecor = (int) (scale * contentInsets.top);
                    int unscaledThumbWidth = (int) (thumbWidth / scale);
                    int unscaledThumbHeight = (int) (thumbHeight / scale);
                    mTmpFromClipRect.set(containingFrame);
                    mTmpToClipRect.set(containingFrame);
                    if (isFullScreen) {
                        mTmpToClipRect.top = contentInsets.top;
                        mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
                    }
                    mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
                }
                // exclude top screen decor (status bar) region from the destination clip.
                mTmpToClipRect.top = contentInsets.top;

                mNextAppTransitionInsets.set(contentInsets);

                Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
@@ -963,7 +953,7 @@ public class AppTransition implements Dump {

    Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
            int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets,
            Rect appFrame, boolean isFullScreen, boolean isVoiceInteraction) {
            Rect appFrame, boolean isVoiceInteraction) {
        Animation a;
        if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
                || transit == TRANSIT_TASK_OPEN
@@ -1033,7 +1023,7 @@ public class AppTransition implements Dump {
                    (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
            a = createAspectScaledThumbnailEnterExitAnimationLocked(
                    getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
                    transit, containingFrame, contentInsets, isFullScreen);
                    transit, containingFrame, contentInsets);
            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
                String animName = mNextAppTransitionScaleUp ?
                        "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
+10 −23
Original line number Diff line number Diff line
@@ -304,11 +304,6 @@ public class WindowManagerService extends IWindowManager.Stub

    private static final int MAX_SCREENSHOT_RETRIES = 3;

    // The flag describing a full screen app window (where the app takes care of drawing under the
    // SystemUI bars)
    private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;

    private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";

    final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -3457,30 +3452,22 @@ public class WindowManagerService extends IWindowManager.Stub
            DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
            final int width = displayInfo.appWidth;
            final int height = displayInfo.appHeight;
            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
                    + atoken);
            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                    "applyAnimation: atoken=" + atoken);

            // Determine the visible rect to calculate the thumbnail clip
            WindowState win = atoken.findMainWindow();
            Rect containingFrame = new Rect(0, 0, width, height);
            Rect contentInsets = new Rect();
            Rect appFrame = new Rect(0, 0, width, height);
            boolean isFullScreen = true;
            if (win != null) {
                if (win.mContainingFrame != null) {
            if (win != null && win.isFullscreen(width, height)) {
                // 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.
                containingFrame.set(win.mContainingFrame);
                }
                if (win.mContentInsets != null) {
                contentInsets.set(win.mContentInsets);
                }
                if (win.mFrame != null) {
                appFrame.set(win.mFrame);
            }
                isFullScreen =
                        ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) ==
                                SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) ||
                                ((win.mAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0);
            }

            if (atoken.mLaunchTaskBehind) {
                // Differentiate the two animations. This one which is briefly on the screen
@@ -3490,7 +3477,7 @@ public class WindowManagerService extends IWindowManager.Stub
            }
            Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
                    mCurConfiguration.orientation, containingFrame, contentInsets, appFrame,
                    isFullScreen, isVoiceInteraction);
                    isVoiceInteraction);
            if (a != null) {
                if (DEBUG_ANIM) {
                    RuntimeException e = null;
+2 −29
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.wm;

import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.server.wm.WindowManagerService.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS;
@@ -1231,10 +1230,6 @@ class WindowStateAnimator {
            mDtDx = 0;
            mDsDy = 0;
            mDtDy = mWin.mGlobalScale;
            if (appTransformation == null) {
                mHasClipRect = false;
                mClipRect.setEmpty();
            }
        }
    }

@@ -1306,9 +1301,9 @@ class WindowStateAnimator {
            applyDecorRect(w.mDecorFrame);
        }

        // By default, the clip rect is the system decor.
        // By default, the clip rect is the system decor if the transformation doesn't specify one.
        final Rect clipRect = mTmpClipRect;
        clipRect.set(w.mSystemDecorRect);
        clipRect.set((mHasClipRect) ? mClipRect : w.mSystemDecorRect);

        // Expand the clip rect for surface insets.
        final WindowManager.LayoutParams attrs = w.mAttrs;
@@ -1317,28 +1312,6 @@ class WindowStateAnimator {
        clipRect.right += attrs.surfaceInsets.right;
        clipRect.bottom += attrs.surfaceInsets.bottom;

        // If we have an animated clip rect, intersect it with the clip rect.
        // However, the clip rect animation effect should be applied on app windows that inset
        // decor only. If applying on non-inset decor one, the top region of this window will
        // be clipped on the end of animation, e.g. dialog activities.
        if (mHasClipRect && (w.mAttrs.flags & LayoutParams.FLAG_LAYOUT_INSET_DECOR) != 0) {
            // NOTE: We are adding a temporary workaround due to the status bar
            // not always reporting the correct system decor rect. In such
            // cases, we take into account the specified content insets as well.
            if ((w.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
                    == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN
                    || (w.mAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
                // Don't apply the workaround to apps explicitly requesting
                // fullscreen layout or when the bars are transparent.
                clipRect.intersect(mClipRect);
            } else {
                final int offsetTop = Math.max(clipRect.top, w.mContentInsets.top);
                clipRect.offset(0, -offsetTop);
                clipRect.intersect(mClipRect);
                clipRect.offset(0, offsetTop);
            }
        }

        // The clip rect was generated assuming (0,0) as the window origin,
        // so we need to translate to match the actual surface coordinates.
        clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);