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

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

Destroy saved surfaces if one of the last visible windows gets removed

Also, if by the time the app is closing, a window is still invisible
in layout (or is already removed), mark the window as mAnimatingExit,
so that the surface is destroyed (or saved again). If it's marked
for removal, the window gets removed as well.

bug: 28913302
Change-Id: Ifa3dc0742f9c8c09d741fd64dcdc01b49075628c
parent b143e3de
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -451,6 +451,16 @@ class AppWindowToken extends WindowToken {
        destroySurfaces();
    }

    void markSavedSurfaceExiting() {
        for (int i = allAppWindows.size() - 1; i >= 0; i--) {
            final WindowState w = allAppWindows.get(i);
            if (w.isAnimatingInvisibleWithSavedSurface()) {
                w.mAnimatingExit = true;
                w.mWinAnimator.mAnimating = true;
            }
        }
    }

    void restoreSavedSurfaces() {
        if (!canRestoreSurfaces()) {
            clearVisibleBeforeClientHidden();
+15 −16
Original line number Diff line number Diff line
@@ -2277,6 +2277,19 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    private void setupWindowForRemoveOnExit(WindowState win) {
        win.mRemoveOnExit = true;
        win.setDisplayLayoutNeeded();
        // Request a focus update as this window's input channel is already gone. Otherwise
        // we could have no focused window in input manager.
        final boolean focusChanged = updateFocusedWindowLocked(
                UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
        mWindowPlacerLocked.performSurfacePlacement();
        if (focusChanged) {
            mInputMonitor.updateInputWindowsLw(false /*force*/);
        }
    }

    public void removeWindow(Session session, IWindow client) {
        synchronized(mWindowMap) {
            WindowState win = windowForClientLocked(session, client, false);
@@ -2358,14 +2371,7 @@ public class WindowManagerService extends IWindowManager.Stub
                // Do not set mAnimatingExit to true here, it will cause the surface to be hidden
                // immediately after the enter animation is done. If the app is not yet drawn then
                // it will show up as a flicker.
                win.mRemoveOnExit = true;
                // Request a focus update as this window's input channel is already gone. Otherwise
                // we could have no focused window in input manager.
                final boolean focusChanged = updateFocusedWindowLocked(
                        UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
                if (focusChanged) {
                    mInputMonitor.updateInputWindowsLw(false /*force*/);
                }
                setupWindowForRemoveOnExit(win);
                Binder.restoreCallingIdentity(origId);
                return;
            }
@@ -2417,17 +2423,10 @@ public class WindowManagerService extends IWindowManager.Stub
                // The exit animation is running or should run... wait for it!
                if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
                        "Not removing " + win + " due to exit animation ");
                win.mRemoveOnExit = true;
                win.setDisplayLayoutNeeded();
                final boolean focusChanged = updateFocusedWindowLocked(
                        UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
                mWindowPlacerLocked.performSurfacePlacement();
                setupWindowForRemoveOnExit(win);
                if (appToken != null) {
                    appToken.updateReportedVisibilityLocked();
                }
                if (focusChanged) {
                    mInputMonitor.updateInputWindowsLw(false /*force*/);
                }
                Binder.restoreCallingIdentity(origId);
                return;
            }
+3 −1
Original line number Diff line number Diff line
@@ -2111,7 +2111,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
    void clearHasSavedSurface() {
        mSurfaceSaved = false;
        mAnimatingWithSavedSurface = false;
        mWasVisibleBeforeClientHidden = false;
        if (mWasVisibleBeforeClientHidden) {
            mAppToken.destroySavedSurfaces();
        }
    }

    boolean clearAnimatingWithSavedSurface() {
+8 −0
Original line number Diff line number Diff line
@@ -1301,6 +1301,14 @@ class WindowSurfacePlacer {
        appsCount = mService.mClosingApps.size();
        for (int i = 0; i < appsCount; i++) {
            AppWindowToken wtoken = mService.mClosingApps.valueAt(i);

            // If we still have some windows animating with saved surfaces that's
            // either invisible or already removed, mark them exiting so that they
            // are disposed of after the exit animation. These are not supposed to
            // be shown, or are delayed removal until app is actually drawn (in which
            // case the window will be removed after the animation).
            wtoken.markSavedSurfaceExiting();

            final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
            appAnimator.clearThumbnail();