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

Commit bef461f6 authored by Chong Zhang's avatar Chong Zhang
Browse files

Several fixes for saved surface

- Do not save if the exiting app is no longer top of task

- Mark saved surfaces as invalid when recoving memory, they will
  be reclaimed if they're hidden.

- Save surface when visibility changed to GONE

- Discard saved surface after rotation

- Misc minor fixes and clean-up

bug: 19940527

Change-Id: I5760c7a7b4bf37ef6bdd39cae793a97cf7579429
parent 7b0181ce
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
package com.android.server.wm;

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_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerService.TAG;

import com.android.server.input.InputApplicationHandle;
import com.android.server.wm.WindowManagerService.H;
@@ -296,6 +299,52 @@ class AppWindowToken extends WindowToken {
        }
    }

    /**
     * Checks whether we should save surfaces for this app.
     *
     * @return true if the surfaces should be saved, false otherwise.
     */
    boolean shouldSaveSurface() {
        // We want to save surface if the app's windows are "allDrawn", or if we're
        // 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 true;
        }
        return false;
    }

    void restoreSavedSurfaces() {
        if (!mHasSavedSurface) {
            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;
        }
    }

    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();
            }
        }
    }

    @Override
    void removeAllWindows() {
        for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
+5 −0
Original line number Diff line number Diff line
@@ -342,6 +342,11 @@ class Task implements DimLayer.DimLayerUser {
        return tokensCount > 0 ? mAppTokens.get(tokensCount - 1).findMainWindow() : null;
    }

    AppWindowToken getTopAppWindowToken() {
        final int tokensCount = mAppTokens.size();
        return tokensCount > 0 ? mAppTokens.get(tokensCount - 1) : null;
    }

    @Override
    public boolean isFullscreen() {
        if (useCurrentBounds()) {
+16 −11
Original line number Diff line number Diff line
@@ -2637,6 +2637,11 @@ public class WindowManagerService extends IWindowManager.Stub
                    }
                }
                dragResizing = win.isDragResizing();
                if (win.isAnimatingWithSavedSurface()) {
                    // If we're animating with a saved surface now, request client to report draw.
                    // We still need to know when the real thing is drawn.
                    toBeDisplayed = true;
                }
                try {
                    if (!win.mHasSurface) {
                        surfaceChanged = true;
@@ -2692,11 +2697,9 @@ public class WindowManagerService extends IWindowManager.Stub
                    // the app sets visibility to invisible for the first time after resume,
                    // or when the user exits immediately after a resume. In both cases, we
                    // don't want to destroy the saved surface.
                    final boolean isAnimatingWithSavedSurface =
                            win.mAppToken != null && win.mAppToken.mAnimatingWithSavedSurface;
                    // If we are not currently running the exit animation, we
                    // need to see about starting one.
                    if (!win.mExiting && !isAnimatingWithSavedSurface) {
                    if (!win.mExiting && !win.isAnimatingWithSavedSurface()) {
                        surfaceChanged = true;
                        // Try starting an animation; if there isn't one, we
                        // can destroy the surface right away.
@@ -2722,8 +2725,10 @@ public class WindowManagerService extends IWindowManager.Stub
                            if (mInputMethodWindow == win) {
                                mInputMethodWindow = null;
                            }
                            if (!win.shouldSaveSurface()) {
                                winAnimator.destroySurfaceLocked();
                            }
                        }
                        //TODO (multidisplay): Magnification is supported only for the default
                        if (mAccessibilityController != null
                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
@@ -2855,12 +2860,6 @@ public class WindowManagerService extends IWindowManager.Stub
                        getDefaultDisplayContentLocked().pendingLayoutChanges |=
                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                    }
                    if (win.mAppToken != null) {
                        // App has drawn something to its windows, we're no longer animating with
                        // the saved surfaces. If the user exits now, we only want to save again
                        // if allDrawn is true.
                        win.mAppToken.mAnimatingWithSavedSurface = false;
                    }
                    win.setDisplayLayoutNeeded();
                    mWindowPlacerLocked.requestTraversal();
                }
@@ -6112,6 +6111,10 @@ public class WindowManagerService extends IWindowManager.Stub
        final WindowList windows = displayContent.getWindowList();
        for (int i = windows.size() - 1; i >= 0; i--) {
            WindowState w = windows.get(i);
            // Discard surface after orientation change, these can't be reused.
            if (w.mAppToken != null) {
                w.mAppToken.destroySavedSurfaces();
            }
            if (w.mHasSurface) {
                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
                w.mOrientationChanging = true;
@@ -8767,12 +8770,14 @@ public class WindowManagerService extends IWindowManager.Stub
                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
                                    + ws + " surface=" + wsa.mSurfaceControl
                                    + " token=" + ws.mAppToken);
                                    + " token=" + ws.mAppToken
                                    + " saved=" + ws.mAppToken.mHasSavedSurface);
                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
                            wsa.mSurfaceControl.destroy();
                            wsa.mSurfaceShown = false;
                            wsa.mSurfaceControl = null;
                            ws.mHasSurface = false;
                            ws.mAppToken.mHasSavedSurface = false;
                            leakedSurface = true;
                        }
                    }
+11 −12
Original line number Diff line number Diff line
@@ -29,6 +29,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_LAYOUT;
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
@@ -1505,29 +1507,26 @@ final class WindowState implements WindowManagerPolicy.WindowState {
        return mExiting || (mService.mClosingApps.contains(mAppToken));
    }

    boolean saveSurfaceIfNeeded() {
    boolean isAnimatingWithSavedSurface() {
        return mAppToken != null && mAppToken.mAnimatingWithSavedSurface;
    }

    boolean shouldSaveSurface() {
        if (ActivityManager.isLowRamDeviceStatic()) {
            // Don't save surfaces on Svelte devices.
            return false;
        }

        Task task = getTask();
        if (task == null || task.inHomeStack()) {
        if (task == null || task.inHomeStack()
                || task.getTopAppWindowToken() != 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;
        }

        // We want to save surface if the app's windows are "allDrawn", or if we're
        // 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.)
        if (mAppToken.allDrawn || mAppToken.mAnimatingWithSavedSurface) {
            mAppToken.mHasSavedSurface = true;
            return true;
        }

        return false;
        return mAppToken.shouldSaveSurface();
    }

    @Override
+6 −0
Original line number Diff line number Diff line
@@ -525,6 +525,12 @@ class WindowStateAnimator {
            Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
                    + drawStateToString());
        }
        if (mWin.mAppToken != null) {
            // App has drawn something to its windows, we're no longer animating with
            // the saved surfaces. If the user exits now, we only want to save again
            // if allDrawn is true.
            mWin.mAppToken.mAnimatingWithSavedSurface = false;
        }
        if (mDrawState == DRAW_PENDING) {
            if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
                Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in "
Loading