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

Commit 12d3a943 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

When a window is first shown only draw once while animating.

On some hardware allocating a new graphics buffer is quite
expensive, which blocks updates to the UI.  This can cause
glitches when performing window animations.

To reduce these glitches, the view hierarchy will now only
allow itself to be drawn once if its window is being shown
while the window manager is animating, not resuming draws
until it is told that the animation is done.

Change-Id: Ie15192f6fddbd0931b022a72c76ddd55ca266d84
parent 11dea294
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -77,4 +77,11 @@ oneway interface IWindow {
     */
    void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
            int localValue, int localChanges);

    /**
     * If the window manager returned RELAYOUT_RES_ANIMATING
     * from relayout(), this method will be called when the animation
     * is done.
     */
    void doneAnimating();
}
+45 −6
Original line number Diff line number Diff line
@@ -229,6 +229,7 @@ public final class ViewRootImpl implements ViewParent,
    boolean mNewSurfaceNeeded;
    boolean mHasHadWindowFocus;
    boolean mLastWasImTarget;
    boolean mWindowsAnimating;
    int mLastSystemUiVisibility;

    // Pool of queued input events.
@@ -1768,6 +1769,8 @@ public final class ViewRootImpl implements ViewParent,
            }
        }

        boolean skipDraw = false;

        if (mFirst) {
            // handle first focus request
            if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="
@@ -1784,6 +1787,14 @@ public final class ViewRootImpl implements ViewParent,
                            + mRealFocusedView);
                }
            }
            if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) != 0) {
                // The first time we relayout the window, if the system is
                // doing window animations, we want to hold of on any future
                // draws until the animation is done.
                mWindowsAnimating = true;
            }
        } else if (mWindowsAnimating) {
            skipDraw = true;
        }

        mFirst = false;
@@ -1815,6 +1826,7 @@ public final class ViewRootImpl implements ViewParent,
                viewVisibility != View.VISIBLE;

        if (!cancelDraw && !newSurface) {
            if (!skipDraw || mReportNextDraw) {
                if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                    for (int i = 0; i < mPendingTransitions.size(); ++i) {
                        mPendingTransitions.get(i).startChangingAnimations();
@@ -1823,6 +1835,7 @@ public final class ViewRootImpl implements ViewParent,
                }
    
                performDraw();
            }
        } else {
            // End any pending transitions on this non-visible window
            if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
@@ -2680,6 +2693,7 @@ public final class ViewRootImpl implements ViewParent,
    private final static int MSG_DISPATCH_SCREEN_STATE = 20;
    private final static int MSG_INVALIDATE_DISPLAY_LIST = 21;
    private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22;
    private final static int MSG_DISPATCH_DONE_ANIMATING = 23;

    final class ViewRootHandler extends Handler {
        @Override
@@ -2729,6 +2743,8 @@ public final class ViewRootImpl implements ViewParent,
                    return "MSG_INVALIDATE_DISPLAY_LIST";
                case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
                    return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
                case MSG_DISPATCH_DONE_ANIMATING:
                    return "MSG_DISPATCH_DONE_ANIMATING";
            }
            return super.getMessageName(message);
        }
@@ -2941,6 +2957,9 @@ public final class ViewRootImpl implements ViewParent,
            case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
                setAccessibilityFocusedHost(null);
            } break;
            case MSG_DISPATCH_DONE_ANIMATING: {
                handleDispatchDoneAnimating();
            } break;
            }
        }
    }
@@ -3756,6 +3775,15 @@ public final class ViewRootImpl implements ViewParent,
        mView.dispatchSystemUiVisibilityChanged(args.globalVisibility);
    }

    public void handleDispatchDoneAnimating() {
        if (mWindowsAnimating) {
            mWindowsAnimating = false;
            if (!mDirty.isEmpty() || mIsAnimating)  {
                scheduleTraversals();
            }
        }
    }

    public void getLastTouchPoint(Point outLocation) {
        outLocation.x = (int) mLastTouchPoint.x;
        outLocation.y = (int) mLastTouchPoint.y;
@@ -4476,6 +4504,10 @@ public final class ViewRootImpl implements ViewParent,
        mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
    }

    public void dispatchDoneAnimating() {
        mHandler.sendEmptyMessage(MSG_DISPATCH_DONE_ANIMATING);
    }

    public void dispatchCheckFocus() {
        if (!mHandler.hasMessages(MSG_CHECK_FOCUS)) {
            // This will result in a call to checkFocus() below.
@@ -4783,6 +4815,13 @@ public final class ViewRootImpl implements ViewParent,
                        localValue, localChanges);
            }
        }

        public void doneAnimating() {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.dispatchDoneAnimating();
            }
        }
    }

    /**
+5 −0
Original line number Diff line number Diff line
@@ -73,6 +73,11 @@ public class WindowManagerImpl implements WindowManager {
     * The window manager has changed the surface from the last call.
     */
    public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
    /**
     * The window manager is currently animating.  It will call
     * IWindow.doneAnimating() when done.
     */
    public static final int RELAYOUT_RES_ANIMATING = 0x8;

    /**
     * Flag for relayout: the client will be later giving
+3 −0
Original line number Diff line number Diff line
@@ -87,4 +87,7 @@ public class BaseIWindow extends IWindow.Stub {
            }
        }
    }

    public void doneAnimating() {
    }
}
+24 −2
Original line number Diff line number Diff line
@@ -423,6 +423,12 @@ public class WindowManagerService extends IWindowManager.Stub
    ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
            = new ArrayList<Pair<WindowState, IRemoteCallback>>();

    /**
     * Windows that have called relayout() while we were running animations,
     * so we need to tell when the animation is done.
     */
    final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();

    /**
     * Used when rebuilding window list to keep track of windows that have
     * been removed.
@@ -2647,6 +2653,7 @@ public class WindowManagerService extends IWindowManager.Stub
        boolean inTouchMode;
        boolean configChanged;
        boolean surfaceChanged = false;
        boolean animating;

        // if they don't have this permission, mask out the status bar bits
        int systemUiVisibility = 0;
@@ -2946,6 +2953,10 @@ public class WindowManagerService extends IWindowManager.Stub
                TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);

            inTouchMode = mInTouchMode;
            animating = mAnimator.mAnimating;
            if (animating && !mRelayoutWhileAnimating.contains(win)) {
                mRelayoutWhileAnimating.add(win);
            }

            mInputMonitor.updateInputWindowsLw(true /*force*/);
        }
@@ -2958,7 +2969,8 @@ public class WindowManagerService extends IWindowManager.Stub

        return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0)
                | (displayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0)
                | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0);
                | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0)
                | (animating ? WindowManagerImpl.RELAYOUT_RES_ANIMATING : 0);
    }

    public void performDeferredDestroyWindow(Session session, IWindow client) {
@@ -8579,6 +8591,16 @@ public class WindowManagerService extends IWindowManager.Stub
            mToBottomApps.clear();
        }

        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
                try {
                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
                } catch (RemoteException e) {
                }
            }
            mRelayoutWhileAnimating.clear();
        }

        if (wallpaperDestroyed) {
            mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0;
        }
Loading