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

Commit 0c4a40ef authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fix wallpaper transition cts test failures

Adjust wallpaper windows if an opening app has a window that can be a
wallpaper target so that the right transition animation can be played.
We previously relied on the chance that a previous layout pass might
have set the target wallpaper correctly.

Bug: 31626368
Test: run-test android.server.cts.ActivityManagerTransitionSelectionTests
Change-Id: Idf5e516f4464944b7a31a55d206f05ca3d4ef407
parent 1edc4ac7
Loading
Loading
Loading
Loading
+118 −98
Original line number Diff line number Diff line
@@ -18,14 +18,10 @@ package com.android.server.wm;

import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -39,6 +35,7 @@ import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.WindowManager;
@@ -384,18 +381,6 @@ class WallpaperController {
        return mWallpaperAnimLayerAdjustment;
    }

    void setAnimLayerAdjustment(WindowState win, int adj) {
        if (win != mWallpaperTarget || mLowerWallpaperTarget != null) {
            return;
        }

        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
        mWallpaperAnimLayerAdjustment = adj;
        for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
            mWallpaperTokens.get(i).adjustAnimLayer(adj);
        }
    }

    private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
        final WindowAnimator winAnimator = mService.mAnimator;
        result.reset();
@@ -477,15 +462,32 @@ class WallpaperController {
        }
    }

    /** Updates the target wallpaper if needed and returns true if an update happened. */
    private boolean updateWallpaperWindowsTarget(
            WindowList windows, FindWallpaperTargetResult result) {

        boolean targetChanged = false;
        WindowState wallpaperTarget = result.wallpaperTarget;
        int wallpaperTargetIndex = result.wallpaperTargetIndex;

        if (mWallpaperTarget != wallpaperTarget
                && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != wallpaperTarget)) {
        if (mWallpaperTarget == wallpaperTarget
                || (mLowerWallpaperTarget != null && mLowerWallpaperTarget == wallpaperTarget)) {

            if (mLowerWallpaperTarget != null) {
                // Is it time to stop animating?
                if (!mLowerWallpaperTarget.isAnimatingLw()
                        || !mUpperWallpaperTarget.isAnimatingLw()) {
                    if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                            "No longer animating wallpaper targets!");
                    mLowerWallpaperTarget = null;
                    mUpperWallpaperTarget = null;
                    mWallpaperTarget = wallpaperTarget;
                    return true;
                }
            }

            return false;
        }

        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);

@@ -494,35 +496,44 @@ class WallpaperController {

        WindowState oldW = mWallpaperTarget;
        mWallpaperTarget = wallpaperTarget;
            targetChanged = true;

        if (wallpaperTarget == null || oldW == null) {
            return true;
        }

        // Now what is happening...  if the current and new targets are animating,
        // then we are in our super special mode!
            if (wallpaperTarget != null && oldW != null) {
        boolean oldAnim = oldW.isAnimatingLw();
        boolean foundAnim = wallpaperTarget.isAnimatingLw();
        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                "New animation: " + foundAnim + " old animation: " + oldAnim);
                if (foundAnim && oldAnim) {

        if (!foundAnim || !oldAnim) {
            return true;
        }

        int oldI = windows.indexOf(oldW);
        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                "New i: " + wallpaperTargetIndex + " old i: " + oldI);
                    if (oldI >= 0) {
                        final boolean newTargetHidden =
                                wallpaperTarget.mAppToken != null && wallpaperTarget.mAppToken.hiddenRequested;
                        final boolean oldTargetHidden =
                                oldW.mAppToken != null && oldW.mAppToken.hiddenRequested;
                        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:"
                                + " old#" + oldI + "=" + oldW + " hidden=" + oldTargetHidden
                                + " new#" + wallpaperTargetIndex + "=" + wallpaperTarget
                                + " hidden=" + newTargetHidden);

        if (oldI < 0) {
            return true;
        }

        final boolean newTargetHidden = wallpaperTarget.mAppToken != null
                && wallpaperTarget.mAppToken.hiddenRequested;
        final boolean oldTargetHidden = oldW.mAppToken != null
                && oldW.mAppToken.hiddenRequested;

        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:" + " old#" + oldI + "="
                + oldW + " hidden=" + oldTargetHidden + " new#" + wallpaperTargetIndex + "="
                + wallpaperTarget + " hidden=" + newTargetHidden);

        // Set the upper and lower wallpaper targets correctly,
        // and make sure that we are positioning the wallpaper below the lower.
        if (wallpaperTargetIndex > oldI) {
            // The new target is on top of the old one.
                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                                    "Found target above old target.");
            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target above old target.");
            mUpperWallpaperTarget = wallpaperTarget;
            mLowerWallpaperTarget = oldW;

@@ -530,14 +541,13 @@ class WallpaperController {
            wallpaperTargetIndex = oldI;
        } else {
            // The new target is below the old one.
                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                                    "Found target below old target.");
            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target below old target.");
            mUpperWallpaperTarget = oldW;
            mLowerWallpaperTarget = wallpaperTarget;
        }

        if (newTargetHidden && !oldTargetHidden) {
                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
                                    "Old wallpaper still the target.");
            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Old wallpaper still the target.");
            // Use the old target if new target is hidden but old target
            // is not. If they're both hidden, still use the new target.
            mWallpaperTarget = oldW;
@@ -545,33 +555,18 @@ class WallpaperController {
                && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
                && (mService.mOpeningApps.contains(oldW.mAppToken)
                || mService.mClosingApps.contains(oldW.mAppToken))) {
                            // If they're both hidden (or both not hidden), prefer the one that's
                            // currently in opening or closing app list, this allows transition
                            // selection logic to better determine the wallpaper status of
                            // opening/closing apps.
            // If they're both hidden (or both not hidden), prefer the one that's currently in
            // opening or closing app list, this allows transition selection logic to better
            // determine the wallpaper status of opening/closing apps.
            mWallpaperTarget = oldW;
        }
                    }
                }
            }

        } else if (mLowerWallpaperTarget != null) {
            // Is it time to stop animating?
            if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "No longer animating wallpaper targets!");
                mLowerWallpaperTarget = null;
                mUpperWallpaperTarget = null;
                mWallpaperTarget = wallpaperTarget;
                targetChanged = true;
            }
        }

        result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
        return targetChanged;
        return true;
    }

    boolean updateWallpaperWindowsTargetByLayer(
            WindowList windows, FindWallpaperTargetResult result) {
    private boolean updateWallpaperWindowsTargetByLayer(WindowList windows,
            FindWallpaperTargetResult result) {

        WindowState wallpaperTarget = result.wallpaperTarget;
        int wallpaperTargetIndex = result.wallpaperTargetIndex;
@@ -621,7 +616,7 @@ class WallpaperController {
        return visible;
    }

    boolean updateWallpaperWindowsPlacement(WindowList windows,
    private boolean updateWallpaperWindowsPlacement(WindowList windows,
            WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {

        // TODO(multidisplay): Wallpapers on main screen only.
@@ -734,6 +729,31 @@ class WallpaperController {
        return transitionReady;
    }

    /**
     * Adjusts the wallpaper windows if the input display has a pending wallpaper layout or one of
     * the opening apps should be a wallpaper target.
     */
    void adjustWallpaperWindowsForAppTransitionIfNeeded(
            DisplayContent dc, ArraySet<AppWindowToken> openingApps, WindowList windows) {
        boolean adjust = false;
        if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
            adjust = true;
        } else {
            for (int i = openingApps.size() - 1; i >= 0; --i) {
                final AppWindowToken token = openingApps.valueAt(i);
                if (token.windowsCanBeWallpaperTarget()) {
                    adjust = true;
                    break;
                }
            }
        }

        if (adjust && adjustWallpaperWindows()) {
            mService.mLayersController.assignLayersLocked(windows);
            dc.setLayoutNeeded();
        }
    }

    void addWallpaperToken(WindowToken token) {
        mWallpaperTokens.add(token);
    }
+43 −45
Original line number Diff line number Diff line
@@ -10,6 +10,17 @@ import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_CLOSE;
import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_OPEN;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
@@ -405,8 +416,7 @@ class WindowSurfacePlacer {

        mService.mRoot.mWallpaperMayChange = false;

        // The top-most window will supply the layout params,
        // and we will determine it below.
        // The top-most window will supply the layout params, and we will determine it below.
        LayoutParams animLp = null;
        int bestAnimLayer = -1;
        boolean fullscreenAnim = false;
@@ -415,21 +425,19 @@ class WindowSurfacePlacer {
        int i;
        for (i = 0; i < appsCount; i++) {
            final AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
            // Clearing the mAnimatingExit flag before entering animation. It's set to
            // true if app window is removed, or window relayout to invisible.
            // This also affects window visibility. We need to clear it *before*
            // maybeUpdateTransitToWallpaper() as the transition selection depends on
            // wallpaper target visibility.
            // Clearing the mAnimatingExit flag before entering animation. It's set to true if app
            // window is removed, or window relayout to invisible. This also affects window
            // visibility. We need to clear it *before* maybeUpdateTransitToWallpaper() as the
            // transition selection depends on wallpaper target visibility.
            wtoken.clearAnimatingFlags();

        }

        // Adjust wallpaper before we pull the lower/upper target, since pending changes
        // (like the clearAnimatingFlags() above) might affect wallpaper target result.
        if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
                mWallpaperControllerLocked.adjustWallpaperWindows()) {
            mService.mLayersController.assignLayersLocked(windows);
            displayContent.setLayoutNeeded();
        }
        // Or, the opening app window should be a wallpaper target.
        mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(displayContent,
                mService.mOpeningApps, windows);

        final WindowState lowerWallpaperTarget =
                mWallpaperControllerLocked.getLowerWallpaperTarget();
@@ -447,15 +455,11 @@ class WindowSurfacePlacer {
            upperWallpaperAppToken = upperWallpaperTarget.mAppToken;
        }

        // Do a first pass through the tokens for two
        // things:
        // (1) Determine if both the closing and opening
        // app token sets are wallpaper targets, in which
        // case special animations are needed
        // (since the wallpaper needs to stay static
        // behind them).
        // (2) Find the layout params of the top-most
        // application window in the tokens, which is
        // Do a first pass through the tokens for two things:
        // (1) Determine if both the closing and opening app token sets are wallpaper targets, in
        // which case special animations are needed (since the wallpaper needs to stay static behind
        // them).
        // (2) Find the layout params of the top-most application window in the tokens, which is
        // what will control the animation theme.
        final int closingAppsCount = mService.mClosingApps.size();
        appsCount = closingAppsCount + mService.mOpeningApps.size();
@@ -496,10 +500,8 @@ class WindowSurfacePlacer {
        transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
                closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget);

        // If all closing windows are obscured, then there is
        // no need to do an animation.  This is the case, for
        // example, when this transition is being done behind
        // the lock screen.
        // If all closing windows are obscured, then there is no need to do an animation. This is
        // the case, for example, when this transition is being done behind the lock screen.
        if (!mService.mPolicy.allowAppAnimationsLw()) {
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                    "Animations disallowed by keyguard or dream.");
@@ -721,8 +723,7 @@ class WindowSurfacePlacer {
            WindowState upperWallpaperTarget) {
        // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
        final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
        final WindowState oldWallpaper =
                mWallpaperControllerLocked.isWallpaperTargetAnimating()
        final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
                ? null : wallpaperTarget;
        final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps;
        final ArraySet<AppWindowToken> closingApps = mService.mClosingApps;
@@ -735,18 +736,17 @@ class WindowSurfacePlacer {
                        + ", closingApps=" + closingApps);
        mService.mAnimateWallpaperWithTarget = false;
        if (closingAppHasWallpaper && openingAppHasWallpaper) {
            if (DEBUG_APP_TRANSITIONS)
                Slog.v(TAG, "Wallpaper animation!");
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
            switch (transit) {
                case AppTransition.TRANSIT_ACTIVITY_OPEN:
                case AppTransition.TRANSIT_TASK_OPEN:
                case AppTransition.TRANSIT_TASK_TO_FRONT:
                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
                case TRANSIT_ACTIVITY_OPEN:
                case TRANSIT_TASK_OPEN:
                case TRANSIT_TASK_TO_FRONT:
                    transit = TRANSIT_WALLPAPER_INTRA_OPEN;
                    break;
                case AppTransition.TRANSIT_ACTIVITY_CLOSE:
                case AppTransition.TRANSIT_TASK_CLOSE:
                case AppTransition.TRANSIT_TASK_TO_BACK:
                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
                case TRANSIT_ACTIVITY_CLOSE:
                case TRANSIT_TASK_CLOSE:
                case TRANSIT_TASK_TO_BACK:
                    transit = TRANSIT_WALLPAPER_INTRA_CLOSE;
                    break;
            }
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
@@ -755,17 +755,15 @@ class WindowSurfacePlacer {
                && !openingApps.contains(oldWallpaper.mAppToken)
                && closingApps.contains(oldWallpaper.mAppToken)) {
            // We are transitioning from an activity with a wallpaper to one without.
            transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                    "New transit away from wallpaper: "
            transit = TRANSIT_WALLPAPER_CLOSE;
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit away from wallpaper: "
                    + AppTransition.appTransitionToString(transit));
        } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw() &&
                openingApps.contains(wallpaperTarget.mAppToken)) {
            // We are transitioning from an activity without
            // a wallpaper to now showing the wallpaper
            transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                    "New transit into wallpaper: "
            transit = TRANSIT_WALLPAPER_OPEN;
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit into wallpaper: "
                    + AppTransition.appTransitionToString(transit));
        } else {
            mService.mAnimateWallpaperWithTarget = true;
@@ -774,7 +772,7 @@ class WindowSurfacePlacer {
    }

    private void processApplicationsAnimatingInPlace(int transit) {
        if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
        if (transit == TRANSIT_TASK_IN_PLACE) {
            // Find the focused window
            final WindowState win = mService.getDefaultDisplayContentLocked().findFocusedWindow();
            if (win != null) {
+13 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.util.Slog;

import java.io.PrintWriter;

import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
@@ -217,6 +218,18 @@ class WindowToken extends WindowContainer<WindowState> {
        return null;
    }

    /** Return true if this token has a window that wants the wallpaper displayed behind it. */
    boolean windowsCanBeWallpaperTarget() {
        for (int j = mChildren.size() - 1; j >= 0; j--) {
            final WindowState w = mChildren.get(j);
            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
                return true;
            }
        }

        return false;
    }

    void hideWallpaperToken(boolean wasDeferred, String reason) {
        for (int j = mChildren.size() - 1; j >= 0; j--) {
            final WindowState wallpaper = mChildren.get(j);