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

Commit 97782b40 authored by Chong Zhang's avatar Chong Zhang
Browse files

Fix flash due to not freezing screen when start/end resizing

Instead of freezing the entire screen, preserve the window's old
surface and put it on a layer that's above other windows (while
still below the screen rotation freeze layer). Only remove the
surface when animation starts after the new drawing is received.

bug: 24715185

Change-Id: I1d2b873d339d672cea0f18679b5622cea69bd449
parent 88470545
Loading
Loading
Loading
Loading
+18 −9
Original line number Diff line number Diff line
@@ -18,8 +18,9 @@ package com.android.server.wm;

import java.io.PrintWriter;

import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowStateAnimator.SurfaceTrace;

import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -42,7 +43,15 @@ class ScreenRotationAnimation {
    static final boolean TWO_PHASE_ANIMATION = false;
    static final boolean USE_CUSTOM_BLACK_FRAME = false;

    static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
    /*
     * Layers for screen rotation animation. We put these layers above
     * WINDOW_FREEZE_LAYER so that screen freeze will cover all windows.
     */
    static final int SCREEN_FREEZE_LAYER_BASE       = WINDOW_FREEZE_LAYER + TYPE_LAYER_MULTIPLIER;
    static final int SCREEN_FREEZE_LAYER_ENTER      = SCREEN_FREEZE_LAYER_BASE;
    static final int SCREEN_FREEZE_LAYER_SCREENSHOT = SCREEN_FREEZE_LAYER_BASE + 1;
    static final int SCREEN_FREEZE_LAYER_EXIT       = SCREEN_FREEZE_LAYER_BASE + 2;
    static final int SCREEN_FREEZE_LAYER_CUSTOM     = SCREEN_FREEZE_LAYER_BASE + 3;

    final Context mContext;
    final DisplayContent mDisplayContent;
@@ -265,7 +274,7 @@ class ScreenRotationAnimation {
                SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
                        SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
                mSurfaceControl.setLayerStack(display.getLayerStack());
                mSurfaceControl.setLayer(FREEZE_LAYER + 1);
                mSurfaceControl.setLayer(SCREEN_FREEZE_LAYER_SCREENSHOT);
                mSurfaceControl.setAlpha(0);
                mSurfaceControl.show();
                sur.destroy();
@@ -545,8 +554,8 @@ class ScreenRotationAnimation {
                Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
                        mOriginalWidth*2, mOriginalHeight*2);
                Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
                mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3,
                        layerStack, false);
                mCustomBlackFrame = new BlackFrame(session, outer, inner,
                        SCREEN_FREEZE_LAYER_CUSTOM, layerStack, false);
                mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
            } catch (OutOfResourcesException e) {
                Slog.w(TAG, "Unable to allocate black surface", e);
@@ -585,8 +594,8 @@ class ScreenRotationAnimation {
                            mOriginalWidth*2, mOriginalHeight*2);
                    inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
                }
                mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2,
                        layerStack, mForceDefaultOrientation);
                mExitingBlackFrame = new BlackFrame(session, outer, inner,
                        SCREEN_FREEZE_LAYER_EXIT, layerStack, mForceDefaultOrientation);
                mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
            } catch (OutOfResourcesException e) {
                Slog.w(TAG, "Unable to allocate black surface", e);
@@ -608,8 +617,8 @@ class ScreenRotationAnimation {
                Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
                        finalWidth*2, finalHeight*2);
                Rect inner = new Rect(0, 0, finalWidth, finalHeight);
                mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER,
                        layerStack, false);
                mEnteringBlackFrame = new BlackFrame(session, outer, inner,
                        SCREEN_FREEZE_LAYER_ENTER, layerStack, false);
            } catch (OutOfResourcesException e) {
                Slog.w(TAG, "Unable to allocate black surface", e);
            } finally {
+3 −0
Original line number Diff line number Diff line
@@ -734,6 +734,9 @@ public class WindowAnimator {
        if (!mAnimating && wasAnimating) {
            mWindowPlacerLocked.requestTraversal();
        }

        mService.destroyPreservedSurfaceLocked();

        if (WindowManagerService.DEBUG_WINDOW_TRACE) {
            Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
                + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams)
+15 −3
Original line number Diff line number Diff line
@@ -399,6 +399,13 @@ public class WindowManagerService extends IWindowManager.Stub
     */
    final ArrayList<WindowState> mDestroySurface = new ArrayList<>();

    /**
     * Windows with a preserved surface waiting to be destroyed. These windows
     * are going through a surface change. We keep the old surface around until
     * the first frame on the new surface finishes drawing.
     */
    final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();

    /**
     * Windows that have lost input focus and are waiting for the new
     * focus window to be displayed before they are told about this.
@@ -2617,9 +2624,7 @@ public class WindowManagerService extends IWindowManager.Stub
                if (win.isDragResizeChanged()) {
                    win.setDragResizing();
                    if (win.mHasSurface) {
                        winAnimator.mDestroyPendingSurfaceUponRedraw = true;
                        winAnimator.mSurfaceDestroyDeferred = true;
                        winAnimator.destroySurfaceLocked();
                        winAnimator.preserveSurfaceLocked();
                        toBeDisplayed = true;
                    }
                }
@@ -7782,6 +7787,13 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    void destroyPreservedSurfaceLocked() {
        for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) {
            final WindowState w = mDestroyPreservedSurface.get(i);
            w.mWinAnimator.destroyPreservedSurfaceLocked();
        }
        mDestroyPreservedSurface.clear();
    }
    // -------------------------------------------------------------
    // IWindowManager API
    // -------------------------------------------------------------
+33 −8
Original line number Diff line number Diff line
@@ -23,11 +23,12 @@ import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerService.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.localLOGV;
import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerService.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerService.localLOGV;
import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;

@@ -66,6 +67,7 @@ import java.util.ArrayList;
 **/
class WindowStateAnimator {
    static final String TAG = "WindowStateAnimator";
    static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;

    // Unchanging local convenience fields.
    final WindowManagerService mService;
@@ -108,7 +110,7 @@ class WindowStateAnimator {
     */
    boolean mSurfaceDestroyDeferred;

    boolean mDestroyPendingSurfaceUponRedraw;
    boolean mDestroyPreservedSurfaceUponRedraw;
    float mShownAlpha = 0;
    float mAlpha = 0;
    float mLastAlpha = 0;
@@ -556,12 +558,10 @@ class WindowStateAnimator {
        if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
            result = performShowLocked();
        }
        if (mDestroyPendingSurfaceUponRedraw) {
            mDestroyPendingSurfaceUponRedraw = false;
            destroyDeferredSurfaceLocked();
            mService.stopFreezingDisplayLocked();
        if (mDestroyPreservedSurfaceUponRedraw && result) {
            mService.mDestroyPreservedSurface.add(mWin);
        }
        return false;
        return result;
    }

    static class SurfaceTrace extends SurfaceControl {
@@ -781,6 +781,31 @@ class WindowStateAnimator {
        }
    }

    void preserveSurfaceLocked() {
        if (mDestroyPreservedSurfaceUponRedraw) {
            return;
        }
        if (mSurfaceControl != null) {
            SurfaceControl.openTransaction();
            try {
                mSurfaceControl.setLayer(WINDOW_FREEZE_LAYER);
            } finally {
                SurfaceControl.closeTransaction();
            }
        }
        mDestroyPreservedSurfaceUponRedraw = true;
        mSurfaceDestroyDeferred = true;
        destroySurfaceLocked();
    }

    void destroyPreservedSurfaceLocked() {
        if (!mDestroyPreservedSurfaceUponRedraw) {
            return;
        }
        destroyDeferredSurfaceLocked();
        mDestroyPreservedSurfaceUponRedraw = false;
    }

    SurfaceControl createSurfaceLocked() {
        final WindowState w = mWin;
        if (mSurfaceControl == null) {