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

Commit 78a08ee8 authored by Filip Gruszczynski's avatar Filip Gruszczynski
Browse files

Fix blink when docking a window.

We need to be very precise about removing the old window when the new
one is shown. The right moment is immediately after the first frame
of the new window entrance animation gets commited. This requires
more infrastructure and flags, rather than depending on the old ones
and hoping that they will match our needs.

Bug: 25075151

Change-Id: I0fdbf38d0915ded3300d75fc7268e619b574bcf5
parent f49bec04
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -133,6 +133,9 @@ class AppWindowToken extends WindowToken {
    // 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;
    // Whether the new window has replaced the old one, so the old one can be removed without
    // blinking.
    boolean mHasReplacedWindow;

    AppWindowToken(WindowManagerService _service, IApplicationToken _token,
            boolean _voiceInteraction) {
+70 −28
Original line number Diff line number Diff line
@@ -18,29 +18,35 @@ package com.android.server.wm;

import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;

import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
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_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerService.DEBUG_KEYGUARD;
import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerService.DEBUG_WINDOW_TRACE;
import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;

import android.content.Context;
import android.os.RemoteException;
import android.os.Trace;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.view.Choreographer;
import android.view.Display;
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.Choreographer;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -101,6 +107,10 @@ public class WindowAnimator {
    static final int KEYGUARD_ANIMATING_OUT = 2;
    int mForceHiding = KEYGUARD_NOT_SHOWN;

    // When set to true the animator will go over all windows after an animation frame is posted and
    // check if some got replaced and can be removed.
    private boolean mRemoveReplacedWindows = false;

    private String forceHidingToString() {
        switch (mForceHiding) {
            case KEYGUARD_NOT_SHOWN:    return "KEYGUARD_NOT_SHOWN";
@@ -164,7 +174,7 @@ public class WindowAnimator {
                        setAppLayoutChanges(appAnimator,
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
                                "appToken " + appAnimator.mAppToken + " done", displayId);
                        if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
                        if (DEBUG_ANIM) Slog.v(TAG,
                                "updateWindowsApps...: done animating " + appAnimator.mAppToken);
                    }
                }
@@ -182,7 +192,7 @@ public class WindowAnimator {
                    setAppLayoutChanges(appAnimator,
                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
                            "exiting appToken " + appAnimator.mAppToken + " done", displayId);
                    if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
                    if (DEBUG_ANIM) Slog.v(TAG,
                            "updateWindowsApps...: done animating exiting "
                                    + appAnimator.mAppToken);
                }
@@ -274,7 +284,7 @@ public class WindowAnimator {
                winAnimator.mWasAnimating = nowAnimating;
                mAnimating |= nowAnimating;

                if (WindowManagerService.DEBUG_WALLPAPER) {
                if (DEBUG_WALLPAPER) {
                    Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
                            ", nowAnimating=" + nowAnimating);
                }
@@ -284,7 +294,7 @@ public class WindowAnimator {
                    mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                    setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                    if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                    if (DEBUG_LAYOUT_REPEATS) {
                        mWindowPlacerLocked.debugLayoutRepeats(
                                "updateWindowsAndWallpaperLocked 2",
                                getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
@@ -293,13 +303,13 @@ public class WindowAnimator {

                if (mPolicy.isForceHiding(win.mAttrs)) {
                    if (!wasAnimating && nowAnimating) {
                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_ANIM ||
                                WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                        if (DEBUG_KEYGUARD || DEBUG_ANIM ||
                                DEBUG_VISIBILITY) Slog.v(TAG,
                                "Animation started that could impact force hide: " + win);
                        mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
                        setPendingLayoutChanges(displayId,
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                        if (DEBUG_LAYOUT_REPEATS) {
                            mWindowPlacerLocked.debugLayoutRepeats(
                                    "updateWindowsAndWallpaperLocked 3",
                                    getPendingLayoutChanges(displayId));
@@ -318,7 +328,7 @@ public class WindowAnimator {
                            mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
                        }
                    }
                    if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                    if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
                            "Force hide " + forceHidingToString()
                            + " hasSurface=" + win.mHasSurface
                            + " policyVis=" + win.mPolicyVisibility
@@ -333,7 +343,7 @@ public class WindowAnimator {
                            // Was already hidden
                            continue;
                        }
                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                        if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
                                "Now policy hidden: " + win);
                    } else {
                        boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
@@ -355,7 +365,7 @@ public class WindowAnimator {
                            win.hideLw(false, false);
                            continue;
                        }
                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                        if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
                                "Now policy shown: " + win);
                        if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
                                && win.mAttachedWindow == null) {
@@ -385,7 +395,7 @@ public class WindowAnimator {
                            // We are showing on top of the current
                            // focus, so re-evaluate focus to make
                            // sure it is correct.
                            if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
                            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
                                    "updateWindowsLocked: setting mFocusMayChange true");
                            mService.mFocusMayChange = true;
                        }
@@ -394,7 +404,7 @@ public class WindowAnimator {
                        mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                        setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                        if (DEBUG_LAYOUT_REPEATS) {
                            mWindowPlacerLocked.debugLayoutRepeats(
                                    "updateWindowsAndWallpaperLocked 4",
                                    getPendingLayoutChanges(Display.DEFAULT_DISPLAY));
@@ -419,7 +429,7 @@ public class WindowAnimator {
                    if (winAnimator.performShowLocked()) {
                        setPendingLayoutChanges(displayId,
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
                        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                        if (DEBUG_LAYOUT_REPEATS) {
                            mWindowPlacerLocked.debugLayoutRepeats(
                                    "updateWindowsAndWallpaperLocked 5",
                                    getPendingLayoutChanges(displayId));
@@ -561,7 +571,7 @@ public class WindowAnimator {
        } // end forall windows

        if (mWindowDetachedWallpaper != detachedWallpaper) {
            if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
            if (DEBUG_WALLPAPER) Slog.v(TAG,
                    "Detached wallpaper changed from " + mWindowDetachedWallpaper
                    + " to " + detachedWallpaper);
            mWindowDetachedWallpaper = detachedWallpaper;
@@ -591,7 +601,7 @@ public class WindowAnimator {
                        if (appAnimator.freezingScreen) {
                            appAnimator.showAllWindowsLocked();
                            mService.unsetAppFreezingScreenLocked(wtoken, false, true);
                            if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
                            if (DEBUG_ORIENTATION) Slog.i(TAG,
                                    "Setting mOrientationChangeComplete=true because wtoken "
                                    + wtoken + " numInteresting=" + wtoken.numInterestingWindows
                                    + " numDrawn=" + wtoken.numDrawnWindows);
@@ -628,11 +638,11 @@ public class WindowAnimator {
        boolean wasAnimating = mAnimating;
        mAnimating = false;
        mAppWindowAnimating = false;
        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
        if (DEBUG_WINDOW_TRACE) {
            Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
        }

        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
        if (SHOW_TRANSACTIONS) Slog.i(
                TAG, ">>> OPEN TRANSACTION animateLocked");
        SurfaceControl.openTransaction();
        SurfaceControl.setAnimationTransaction();
@@ -707,7 +717,7 @@ public class WindowAnimator {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
            SurfaceControl.closeTransaction();
            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
            if (SHOW_TRANSACTIONS) Slog.i(
                    TAG, "<<< CLOSE TRANSACTION animateLocked");
        }

@@ -744,9 +754,13 @@ public class WindowAnimator {
            }
        }

        if (mRemoveReplacedWindows) {
            removeReplacedWindowsLocked();
        }

        mService.destroyPreservedSurfaceLocked();

        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
        if (DEBUG_WINDOW_TRACE) {
            Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
                    + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
                    + " mPendingLayoutChanges(DEFAULT_DISPLAY)="
@@ -754,6 +768,26 @@ public class WindowAnimator {
        }
    }

    private void removeReplacedWindowsLocked() {
        if (SHOW_TRANSACTIONS) Slog.i(
                TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
        SurfaceControl.openTransaction();
        try {
            for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
                DisplayContent display = mService.mDisplayContents.get(i);
                final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
                for (int j = windows.size() - 1; j >= 0; j--) {
                    windows.get(j).maybeRemoveReplacedWindow();
                }
            }
        } finally {
            SurfaceControl.closeTransaction();
            if (SHOW_TRANSACTIONS) Slog.i(
                    TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
        }
        mRemoveReplacedWindows = false;
    }

    private static String bulkUpdateParamsToString(int bulkUpdateParams) {
        StringBuilder builder = new StringBuilder(128);
        if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
@@ -844,7 +878,7 @@ public class WindowAnimator {
        for (int i = windows.size() - 1; i >= 0; i--) {
            if (displayId == windows.get(i).getDisplayId()) {
                setPendingLayoutChanges(displayId, changes);
                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
                if (DEBUG_LAYOUT_REPEATS) {
                    mWindowPlacerLocked.debugLayoutRepeats(reason,
                            getPendingLayoutChanges(displayId));
                }
@@ -875,6 +909,14 @@ public class WindowAnimator {
        return getDisplayContentsAnimatorLocked(displayId).mScreenRotationAnimation;
    }

    void requestRemovalOfReplacedWindows(WindowState win) {
        final AppWindowToken token = win.mAppToken;
        if (token != null && token.mWillReplaceWindow && token.mReplacingWindow == win) {
            token.mHasReplacedWindow = true;
        }
        mRemoveReplacedWindows = true;
    }

    private class DisplayContentsAnimator {
        ScreenRotationAnimation mScreenRotationAnimation = null;
    }
+4 −3
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ import android.animation.ValueAnimator;
import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.StatusBarManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -226,6 +225,7 @@ public class WindowManagerService extends IWindowManager.Stub
    static final boolean SHOW_SURFACE_ALLOC = false;
    static final boolean SHOW_TRANSACTIONS = false;
    static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
    static final boolean SHOW_VERBOSE_TRANSACTIONS = false && SHOW_TRANSACTIONS;
    static final boolean HIDE_STACK_CRAWLS = true;
    static final int LAYOUT_REPEAT_THRESHOLD = 4;

@@ -5627,7 +5627,7 @@ public class WindowManagerService extends IWindowManager.Stub
                }
            }

            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
            if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG,
                    ">>> OPEN TRANSACTION showStrictModeViolation");
            SurfaceControl.openTransaction();
            try {
@@ -5639,7 +5639,7 @@ public class WindowManagerService extends IWindowManager.Stub
                mStrictModeFlash.setVisibility(on);
            } finally {
                SurfaceControl.closeTransaction();
                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG,
                        "<<< CLOSE TRANSACTION showStrictModeViolation");
            }
        }
@@ -10116,6 +10116,7 @@ public class WindowManagerService extends IWindowManager.Stub
            if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Marking app token " + appWindowToken
                    + " as replacing window.");
            appWindowToken.mWillReplaceWindow = true;
            appWindowToken.mHasReplacedWindow = false;
            appWindowToken.mAnimateReplacingWindow = animate;
        }
    }
+4 −2
Original line number Diff line number Diff line
@@ -1374,14 +1374,16 @@ final class WindowState implements WindowManagerPolicy.WindowState {

    void maybeRemoveReplacedWindow() {
        AppWindowToken token = mAppToken;
        if (token != null && token.mWillReplaceWindow && token.mReplacingWindow == this) {
        if (token != null && token.mWillReplaceWindow && token.mReplacingWindow == this
                && token.mHasReplacedWindow) {
            if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replacing window: " + this);
            token.mWillReplaceWindow = false;
            token.mAnimateReplacingWindow = false;
            token.mReplacingRemoveRequested = false;
            token.mReplacingWindow = null;
            token.mHasReplacedWindow = false;
            for (int i = token.allAppWindows.size() - 1; i >= 0; i--) {
                WindowState win = token.allAppWindows.get(i);
                final WindowState win = token.allAppWindows.get(i);
                if (win.mExiting) {
                    mService.removeWindowInnerLocked(win);
                }
+1 −4
Original line number Diff line number Diff line
@@ -1287,6 +1287,7 @@ class WindowStateAnimator {

            if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
                if (showSurfaceRobustlyLocked()) {
                    mAnimator.requestRemovalOfReplacedWindows(w);
                    mLastHidden = false;
                    if (mIsWallpaper) {
                        mWallpaperControllerLocked.dispatchWallpaperVisibility(w, true);
@@ -1472,12 +1473,8 @@ class WindowStateAnimator {
                }
                mWin.mAppToken.updateReportedVisibilityLocked();
            }

            mWin.maybeRemoveReplacedWindow();

            return true;
        }

        return false;
    }

Loading