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

Commit 827e0fac authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Make sure the app can draw a frame before unlocking

- The mechanism to stop windows drawing while window animator was
animating was somehow flaky. It relied on the fact that the client
would call relayout() whenever the animating state changed. This is
mostly the case, but not for lockscreen animations. Instead, we now
use a push model, where window manager tells the app that the state
has changed.
- In addition, it only stopped drawing if that window was animating,
but then only resumed drawing after all windows have finished
animating. Now, we do this per window, so we only stop drawing for
windows that are currently animating.
- We resume the top activity now at the very beginning of the
unlocking sequence. This gives the app a chance to draw a frame
before the user sees anything. If it's to slow, then we just use the
outdated framebuffer.

Bug: 19964562
Change-Id: Ifef8abd189a3146d854b81b9b948861e4d38c155
parent e1d0188b
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -2069,6 +2069,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }

        case KEYGUARD_GOING_AWAY_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            keyguardGoingAway(data.readInt() != 0, data.readInt() != 0);
            reply.writeNoException();
            return true;
        }

        case SHOULD_UP_RECREATE_TASK_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder token = data.readStrongBinder();
@@ -5179,6 +5186,19 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
    }

    public void keyguardGoingAway(boolean disableWindowAnimations,
            boolean keyguardGoingToNotificationShade) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(disableWindowAnimations ? 1 : 0);
        data.writeInt(keyguardGoingToNotificationShade ? 1 : 0);
        mRemote.transact(KEYGUARD_GOING_AWAY_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

    public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
            throws RemoteException {
        Parcel data = Parcel.obtain();
+4 −0
Original line number Diff line number Diff line
@@ -403,6 +403,9 @@ public interface IActivityManager extends IInterface {

    public void keyguardWaitingForActivityDrawn() throws RemoteException;

    public void keyguardGoingAway(boolean disableWindowAnimations,
            boolean keyguardGoingToNotificationShade) throws RemoteException;

    public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
            throws RemoteException;

@@ -842,4 +845,5 @@ public interface IActivityManager extends IInterface {
    int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294;
    int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295;
    int UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
    int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
}
+10 −4
Original line number Diff line number Diff line
@@ -80,11 +80,17 @@ oneway interface IWindow {
            int localValue, int localChanges);

    /**
     * If the window manager returned RELAYOUT_RES_ANIMATING
     * from relayout(), this method will be called when the animation
     * is done.
     * The window is beginning to animate. The application should stop drawing frames until the
     * window is not animating anymore, indicated by being called {@link #windowEndAnimating}.
     *
     * @param remainingFrameCount how many frames the app might still draw before stopping drawing
     */
    void onAnimationStarted(int remainingFrameCount);

    /**
     * The window has ended animating. See {@link #onAnimationStarted}.
     */
    void doneAnimating();
    void onAnimationStopped();

    /**
     * Called for non-application windows when the enter animation has completed.
+51 −28
Original line number Diff line number Diff line
@@ -220,6 +220,9 @@ public final class ViewRootImpl implements ViewParent,
    boolean mLastWasImTarget;
    boolean mWindowsAnimating;
    boolean mDrawDuringWindowsAnimating;

    /** How many frames the app is still allowed to draw when a window animation is happening. */
    private int mRemainingFrameCount;
    boolean mIsDrawing;
    int mLastSystemUiVisibility;
    int mClientWindowLayoutFlags;
@@ -1569,10 +1572,6 @@ public final class ViewRootImpl implements ViewParent,
                }
                final int surfaceGenerationId = mSurface.getGenerationId();
                relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
                if (!mDrawDuringWindowsAnimating &&
                        (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_ANIMATING) != 0) {
                    mWindowsAnimating = true;
                }

                if (DEBUG_LAYOUT) Log.v(TAG, "relayout: frame=" + frame.toShortString()
                        + " overscan=" + mPendingOverscanInsets.toShortString()
@@ -1996,15 +1995,12 @@ public final class ViewRootImpl implements ViewParent,
                            + mView.findFocus());
                }
            }
            if ((relayoutResult & WindowManagerGlobal.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) {
            if (mRemainingFrameCount <= 0) {
                skipDraw = true;
            }
            mRemainingFrameCount--;
        }

        mFirst = false;
        mWillDrawSoon = false;
@@ -2800,7 +2796,7 @@ public final class ViewRootImpl implements ViewParent,
    public void setDrawDuringWindowsAnimating(boolean value) {
        mDrawDuringWindowsAnimating = value;
        if (value) {
            handleDispatchDoneAnimating();
            handleDispatchWindowAnimationStopped();
        }
    }

@@ -3152,11 +3148,12 @@ public final class ViewRootImpl implements ViewParent,
    private final static int MSG_UPDATE_CONFIGURATION = 18;
    private final static int MSG_PROCESS_INPUT_EVENTS = 19;
    private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 21;
    private final static int MSG_DISPATCH_DONE_ANIMATING = 22;
    private final static int MSG_INVALIDATE_WORLD = 23;
    private final static int MSG_WINDOW_MOVED = 24;
    private final static int MSG_SYNTHESIZE_INPUT_EVENT = 25;
    private final static int MSG_DISPATCH_WINDOW_SHOWN = 26;
    private final static int MSG_INVALIDATE_WORLD = 22;
    private final static int MSG_WINDOW_MOVED = 23;
    private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24;
    private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
    private final static int MSG_DISPATCH_WINDOW_ANIMATION_STOPPED = 26;
    private final static int MSG_DISPATCH_WINDOW_ANIMATION_STARTED = 27;

    final class ViewRootHandler extends Handler {
        @Override
@@ -3200,8 +3197,10 @@ public final class ViewRootImpl implements ViewParent,
                    return "MSG_PROCESS_INPUT_EVENTS";
                case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
                    return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
                case MSG_DISPATCH_DONE_ANIMATING:
                    return "MSG_DISPATCH_DONE_ANIMATING";
                case MSG_DISPATCH_WINDOW_ANIMATION_STARTED:
                    return "MSG_DISPATCH_WINDOW_ANIMATION_STARTED";
                case MSG_DISPATCH_WINDOW_ANIMATION_STOPPED:
                    return "MSG_DISPATCH_WINDOW_ANIMATION_STOPPED";
                case MSG_WINDOW_MOVED:
                    return "MSG_WINDOW_MOVED";
                case MSG_SYNTHESIZE_INPUT_EVENT:
@@ -3421,8 +3420,12 @@ public final class ViewRootImpl implements ViewParent,
            case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
                setAccessibilityFocus(null, null);
            } break;
            case MSG_DISPATCH_DONE_ANIMATING: {
                handleDispatchDoneAnimating();
            case MSG_DISPATCH_WINDOW_ANIMATION_STARTED: {
                int remainingFrameCount = msg.arg1;
                handleDispatchWindowAnimationStarted(remainingFrameCount);
            } break;
            case MSG_DISPATCH_WINDOW_ANIMATION_STOPPED: {
                handleDispatchWindowAnimationStopped();
            } break;
            case MSG_INVALIDATE_WORLD: {
                if (mView != null) {
@@ -4038,7 +4041,7 @@ public final class ViewRootImpl implements ViewParent,
            } else {
                // If delivering a new non-key event, make sure the window is
                // now allowed to start updating.
                handleDispatchDoneAnimating();
                handleDispatchWindowAnimationStopped();
                final int source = q.mEvent.getSource();
                if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                    return processPointerEvent(q);
@@ -4068,7 +4071,7 @@ public final class ViewRootImpl implements ViewParent,
            if (event.getAction() != KeyEvent.ACTION_UP) {
                // If delivering a new key event, make sure the window is
                // now allowed to start updating.
                handleDispatchDoneAnimating();
                handleDispatchWindowAnimationStopped();
            }

            // Deliver the key to the view hierarchy.
@@ -5285,7 +5288,14 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    public void handleDispatchDoneAnimating() {
    public void handleDispatchWindowAnimationStarted(int remainingFrameCount) {
        if (!mDrawDuringWindowsAnimating) {
            mRemainingFrameCount = remainingFrameCount;
            mWindowsAnimating = true;
        }
    }

    public void handleDispatchWindowAnimationStopped() {
        if (mWindowsAnimating) {
            mWindowsAnimating = false;
            if (!mDirty.isEmpty() || mIsAnimating || mFullRedrawNeeded)  {
@@ -6189,8 +6199,13 @@ 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 dispatchWindowAnimationStarted(int remainingFrameCount) {
        mHandler.obtainMessage(MSG_DISPATCH_WINDOW_ANIMATION_STARTED,
                remainingFrameCount, 0 /* unused */).sendToTarget();
    }

    public void dispatchWindowAnimationStopped() {
        mHandler.sendEmptyMessage(MSG_DISPATCH_WINDOW_ANIMATION_STOPPED);
    }

    public void dispatchCheckFocus() {
@@ -6713,10 +6728,18 @@ public final class ViewRootImpl implements ViewParent,
        }

        @Override
        public void doneAnimating() {
        public void onAnimationStarted(int remainingFrameCount) {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.dispatchWindowAnimationStarted(remainingFrameCount);
            }
        }

        @Override
        public void onAnimationStopped() {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.dispatchDoneAnimating();
                viewAncestor.dispatchWindowAnimationStopped();
            }
        }

+0 −6
Original line number Diff line number Diff line
@@ -68,12 +68,6 @@ public final class WindowManagerGlobal {
     */
    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
     * internal insets; as a result, the window will not impact other window
Loading