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

Commit 13f7be9e authored by Robert Carr's avatar Robert Carr
Browse files

Move surface save state tracking to WindowState.

In the current set up, surface saving is managed by the app window
token. So when destroySavedSurfaces is called, all saved surfaces
assosciated with a given app will be destroyed. This causes pretty weird
behavior where hiding child windows can destroy the parent window. We
move this tracking to WindowState and allow child windows to exempt themselves.

Bug: 25780116
Change-Id: I3ab92221d83297092dfd98a71e6a5fe96381de8b
parent 28be2bdb
Loading
Loading
Loading
Loading
+14 −19
Original line number Diff line number Diff line
@@ -54,10 +54,6 @@ class AppWindowToken extends WindowToken {

    final boolean voiceInteraction;

    // Whether the window has a saved surface from last pause, which can be
    // used to start an entering animation earlier.
    boolean mHasSavedSurface;

    // Whether we're performing an entering animation with a saved surface.
    boolean mAnimatingWithSavedSurface;

@@ -316,39 +312,38 @@ class AppWindowToken extends WindowToken {
        // currently animating with save surfaces. (If the app didn't even finish
        // drawing when the user exits, but we have a saved surface from last time,
        // we still want to keep that surface.)
        mHasSavedSurface = allDrawn || mAnimatingWithSavedSurface;
        if (mHasSavedSurface) {
            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                    "Saving surface: " + this);
        return allDrawn || mAnimatingWithSavedSurface;
    }

    boolean hasSavedSurface() {
        for (int i = windows.size() -1; i >= 0; i--) {
            final WindowState ws = windows.get(i);
            if (ws.hasSavedSurface()) {
                return true;
            }
        }
        return false;
    }

    void restoreSavedSurfaces() {
        if (!mHasSavedSurface) {
        if (!hasSavedSurface()) {
            return;
        }

        if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                "Restoring saved surfaces: " + this + ", allDrawn=" + allDrawn);

        mHasSavedSurface = false;
        mAnimatingWithSavedSurface = true;
        for (int i = windows.size() - 1; i >= 0; i--) {
            WindowState ws = windows.get(i);
            ws.mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
            ws.restoreSavedSurface();
        }
    }

    void destroySavedSurfaces() {
        if (mHasSavedSurface) {
            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                    "Destroying saved surface: " + this);
        for (int i = windows.size() - 1; i >= 0; i--) {
                final WindowState win = windows.get(i);
                win.mWinAnimator.destroySurfaceLocked();
            }
            WindowState win = windows.get(i);
            win.destroySavedSurface();
        }
    }

+2 −5
Original line number Diff line number Diff line
@@ -2814,9 +2814,7 @@ public class WindowManagerService extends IWindowManager.Stub
            if (mInputMethodWindow == win) {
                mInputMethodWindow = null;
            }
            if (!win.shouldSaveSurface()) {
                winAnimator.destroySurfaceLocked();
            }
            win.destroyOrSaveSurface();
        }
        //TODO (multidisplay): Magnification is supported only for the default
        if (mAccessibilityController != null
@@ -8966,11 +8964,10 @@ public class WindowManagerService extends IWindowManager.Stub
                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
                                    + ws + " surface=" + wsa.mSurfaceController
                                    + " token=" + ws.mAppToken
                                    + " saved=" + ws.mAppToken.mHasSavedSurface);
                                    + " saved=" + ws.mAppToken.hasSavedSurface());
                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
                            wsa.destroySurface();
                            ws.setHasSurface(false);
                            ws.mAppToken.mHasSavedSurface = false;
                            leakedSurface = true;
                        }
                    }
+37 −8
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerService.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerService.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerService.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerService.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
@@ -402,6 +404,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
    /** When true this window can be displayed on screens owther than mOwnerUid's */
    private boolean mShowToOwnerOnly;

    // Whether the window has a saved surface from last pause, which can be
    // used to start an entering animation earlier.
    public boolean mSurfaceSaved = false;

    /**
     * Wake lock for drawing.
     * Even though it's slightly more expensive to do so, we will use a separate wake lock
@@ -1670,22 +1676,45 @@ final class WindowState implements WindowManagerPolicy.WindowState {
        return mAppToken != null && mAppToken.mAnimatingWithSavedSurface;
    }

    boolean shouldSaveSurface() {
    // Returns true if the surface is saved.
    boolean destroyOrSaveSurface() {
        Task task = getTask();
        if (ActivityManager.isLowRamDeviceStatic()) {
            // Don't save surfaces on Svelte devices.
            return false;
        }

        Task task = getTask();
        if (task == null || task.inHomeStack()
            mSurfaceSaved = false;
        } else if (task == null || task.inHomeStack()
                || task.getTopVisibleAppToken() != mAppToken) {
            // Don't save surfaces for home stack apps. These usually resume and draw
            // first frame very fast. Saving surfaces are mostly a waste of memory.
            // Don't save if the window is not the topmost window.
            return false;
            mSurfaceSaved = false;
        } else if (mAttachedWindow != null) {
            mSurfaceSaved = false;
        } else {
            mSurfaceSaved = mAppToken.shouldSaveSurface();
        }
        if (mSurfaceSaved == false) {
            mWinAnimator.destroySurfaceLocked();
        }
        return mSurfaceSaved;
    }

    public void destroySavedSurface() {
        if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                "Destroying saved surface: " + this);

        if (mSurfaceSaved) {
            mWinAnimator.destroySurfaceLocked();
        }
    }

    public boolean hasSavedSurface() {
        return mSurfaceSaved;
    }

        return mAppToken.shouldSaveSurface();
    public void restoreSavedSurface() {
        mSurfaceSaved = false;
        mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
    }

    @Override
+2 −1
Original line number Diff line number Diff line
@@ -726,13 +726,14 @@ class WindowStateAnimator {
    void destroySurfaceLocked() {
        final AppWindowToken wtoken = mWin.mAppToken;
        if (wtoken != null) {
            wtoken.mHasSavedSurface = false;
            wtoken.mAnimatingWithSavedSurface = false;
            if (mWin == wtoken.startingWindow) {
                wtoken.startingDisplayed = false;
            }
        }

        mWin.mSurfaceSaved = false;

        if (mSurfaceController != null) {
            int i = mWin.mChildWindows.size();
            // When destroying a surface we want to make sure child windows
+2 −4
Original line number Diff line number Diff line
@@ -394,9 +394,7 @@ class WindowSurfacePlacer {
                if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
                    wallpaperDestroyed = true;
                }
                if (!win.shouldSaveSurface()) {
                    win.mWinAnimator.destroySurfaceLocked();
                }
                win.destroyOrSaveSurface();
            } while (i > 0);
            mService.mDestroySurface.clear();
        }
@@ -1252,7 +1250,7 @@ class WindowSurfacePlacer {
                        + wtoken.startingDisplayed + " startingMoved="
                        + wtoken.startingMoved);

                if (wtoken.mHasSavedSurface || wtoken.mAnimatingWithSavedSurface) {
                if (wtoken.hasSavedSurface() || wtoken.mAnimatingWithSavedSurface) {
                    continue;
                }
                if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {