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

Commit 743129f5 authored by Tiger Huang's avatar Tiger Huang
Browse files

Update surface position while there is no surface animation playing

Previous logic uses getAnimationType to know if there will be a surface
update caused by the insets animation. However, if the animation is
played by the InsetsAnimationThreadControlRunner, the animation will be
finished first, and then the runner will post a message to the main UI
thread to remove the animation from mRunningAnimations. That would
produce a time that a control is not being animated, but
InsetsSourceConsumer still thinks it is being animated and skips
updating the surface position.

This CL creates a thread-safe method:

    InsetsAnimationControlRunner#willUpdateSurface

which returns false if a runner is finished or cancelled, and
InsetsSourceConsumer can update the surface based on it.

Fix: 379967370
Fix: 394229693
Flag: EXEMPT bugfix
Test: Show gesture navigation bar from immersive mode and change the
      screen orientation from landscape to portrait. Make sure the
      navigation bar position is correct.
Change-Id: I1d84511082a50a56cda6ca060620b53a3261430f
parent 771c6c3e
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -256,6 +256,11 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro
        }
        }
    }
    }


    @Override
    public boolean willUpdateSurface() {
        return !mFinished && !mCancelled;
    }

    @Override
    @Override
    public @AnimationType int getAnimationType() {
    public @AnimationType int getAnimationType() {
        return mAnimationType;
        return mAnimationType;
+6 −0
Original line number Original line Diff line number Diff line
@@ -54,6 +54,12 @@ public interface InsetsAnimationControlRunner {
     */
     */
    void updateSurfacePosition(SparseArray<InsetsSourceControl> controls);
    void updateSurfacePosition(SparseArray<InsetsSourceControl> controls);


    /**
     * Returns {@code true} if this runner will keep playing the animation and updating the surface.
     * {@code false} otherwise.
     */
    boolean willUpdateSurface();

    /**
    /**
     * Cancels the animation.
     * Cancels the animation.
     */
     */
+12 −1
Original line number Original line Diff line number Diff line
@@ -89,7 +89,7 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
        }
        }
    };
    };


    private SurfaceParamsApplier mSurfaceParamsApplier = new SurfaceParamsApplier() {
    private final SurfaceParamsApplier mSurfaceParamsApplier = new SurfaceParamsApplier() {


        private final float[] mTmpFloat9 = new float[9];
        private final float[] mTmpFloat9 = new float[9];


@@ -168,6 +168,17 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
        }
        }
    }
    }


    @Override
    @UiThread
    public boolean willUpdateSurface() {
        synchronized (mControl) {
            // This is called from the UI thread, however, applyChangeInsets would be called on the
            // animation thread, so we need this critical section to ensure this is not called
            // during applyChangeInsets. See: scheduleApplyChangeInsets.
            return mControl.willUpdateSurface();
        }
    }

    @Override
    @Override
    @UiThread
    @UiThread
    public void cancel() {
    public void cancel() {
+36 −20
Original line number Original line Diff line number Diff line
@@ -1747,9 +1747,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        mTypesBeingCancelled |= types;
        mTypesBeingCancelled |= types;
        try {
        try {
            for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
            for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
                InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
                final InsetsAnimationControlRunner runner = mRunningAnimations.get(i).runner;
                if ((control.getTypes() & types) != 0) {
                if ((runner.getTypes() & types) != 0) {
                    cancelAnimation(control, true /* invokeCallback */);
                    cancelAnimation(runner, true /* invokeCallback */);
                }
                }
            }
            }
            if ((types & ime()) != 0) {
            if ((types & ime()) != 0) {
@@ -1807,10 +1807,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    void notifyControlRevoked(InsetsSourceConsumer consumer) {
    void notifyControlRevoked(InsetsSourceConsumer consumer) {
        final @InsetsType int type = consumer.getType();
        final @InsetsType int type = consumer.getType();
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
            InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
            final InsetsAnimationControlRunner runner = mRunningAnimations.get(i).runner;
            control.notifyControlRevoked(type);
            runner.notifyControlRevoked(type);
            if (control.getControllingTypes() == 0) {
            if (runner.getControllingTypes() == 0) {
                cancelAnimation(control, true /* invokeCallback */);
                cancelAnimation(runner, true /* invokeCallback */);
            }
            }
        }
        }
        if (type == ime()) {
        if (type == ime()) {
@@ -1823,38 +1823,38 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        }
        }
    }
    }


    private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
    private void cancelAnimation(InsetsAnimationControlRunner runner, boolean invokeCallback) {
        if (invokeCallback) {
        if (invokeCallback) {
            ImeTracker.forLogging().onCancelled(control.getStatsToken(),
            ImeTracker.forLogging().onCancelled(runner.getStatsToken(),
                    ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
                    ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
            control.cancel();
            runner.cancel();
        } else {
        } else {
            // Succeeds if invokeCallback is false (i.e. when called from notifyFinished).
            // Succeeds if invokeCallback is false (i.e. when called from notifyFinished).
            ImeTracker.forLogging().onProgress(control.getStatsToken(),
            ImeTracker.forLogging().onProgress(runner.getStatsToken(),
                    ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
                    ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
        }
        }
        if (DEBUG) {
        if (DEBUG) {
            Log.d(TAG, TextUtils.formatSimple(
            Log.d(TAG, TextUtils.formatSimple(
                    "cancelAnimation of types: %d, animType: %d, host: %s",
                    "cancelAnimation of types: %d, animType: %d, host: %s",
                    control.getTypes(), control.getAnimationType(), mHost.getRootViewTitle()));
                    runner.getTypes(), runner.getAnimationType(), mHost.getRootViewTitle()));
        }
        }
        @InsetsType int removedTypes = 0;
        @InsetsType int removedTypes = 0;
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
            RunningAnimation runningAnimation = mRunningAnimations.get(i);
            RunningAnimation runningAnimation = mRunningAnimations.get(i);
            if (runningAnimation.runner == control) {
            if (runningAnimation.runner == runner) {
                mRunningAnimations.remove(i);
                mRunningAnimations.remove(i);
                removedTypes = control.getTypes();
                removedTypes = runner.getTypes();
                if (invokeCallback) {
                if (invokeCallback) {
                    dispatchAnimationEnd(runningAnimation.runner.getAnimation());
                    dispatchAnimationEnd(runningAnimation.runner.getAnimation());
                } else {
                } else {
                    if (Flags.refactorInsetsController()) {
                    if (Flags.refactorInsetsController()) {
                        if ((removedTypes & ime()) != 0
                        if ((removedTypes & ime()) != 0
                                && control.getAnimationType() == ANIMATION_TYPE_HIDE) {
                                && runner.getAnimationType() == ANIMATION_TYPE_HIDE) {
                            if (mHost != null) {
                            if (mHost != null) {
                                // if the (hide) animation is cancelled, the
                                // if the (hide) animation is cancelled, the
                                // requestedVisibleTypes should be reported at this point.
                                // requestedVisibleTypes should be reported at this point.
                                reportRequestedVisibleTypes(!Flags.reportAnimatingInsetsTypes()
                                reportRequestedVisibleTypes(!Flags.reportAnimatingInsetsTypes()
                                        ? control.getStatsToken() : null);
                                        ? runner.getStatsToken() : null);
                                mHost.getInputMethodManager().removeImeSurface(
                                mHost.getInputMethodManager().removeImeSurface(
                                        mHost.getWindowToken());
                                        mHost.getWindowToken());
                            }
                            }
@@ -1869,9 +1869,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            if (mHost != null) {
            if (mHost != null) {
                final boolean dispatchStatsToken =
                final boolean dispatchStatsToken =
                        Flags.reportAnimatingInsetsTypes() && (removedTypes & ime()) != 0
                        Flags.reportAnimatingInsetsTypes() && (removedTypes & ime()) != 0
                                && control.getAnimationType() == ANIMATION_TYPE_HIDE;
                                && runner.getAnimationType() == ANIMATION_TYPE_HIDE;
                mHost.updateAnimatingTypes(mAnimatingTypes,
                mHost.updateAnimatingTypes(mAnimatingTypes,
                        dispatchStatsToken ? control.getStatsToken() : null);
                        dispatchStatsToken ? runner.getStatsToken() : null);
            }
            }
        }
        }


@@ -1959,14 +1959,30 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    @VisibleForTesting(visibility = PACKAGE)
    @VisibleForTesting(visibility = PACKAGE)
    public @AnimationType int getAnimationType(@InsetsType int type) {
    public @AnimationType int getAnimationType(@InsetsType int type) {
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
            InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
            final InsetsAnimationControlRunner runner = mRunningAnimations.get(i).runner;
            if (control.controlsType(type)) {
            if (runner.controlsType(type)) {
                return mRunningAnimations.get(i).type;
                return mRunningAnimations.get(i).type;
            }
            }
        }
        }
        return ANIMATION_TYPE_NONE;
        return ANIMATION_TYPE_NONE;
    }
    }


    /**
     * Returns {@code true} if there is an animation which controls the given {@link InsetsType} and
     * the runner is still playing the surface animation.
     *
     * @see InsetsAnimationControlRunner#willUpdateSurface()
     */
    boolean hasSurfaceAnimation(@InsetsType int type) {
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
            final InsetsAnimationControlRunner runner = mRunningAnimations.get(i).runner;
            if (runner.controlsType(type) && runner.willUpdateSurface()) {
                return true;
            }
        }
        return false;
    }

    @VisibleForTesting(visibility = PACKAGE)
    @VisibleForTesting(visibility = PACKAGE)
    public void setRequestedVisibleTypes(@InsetsType int visibleTypes, @InsetsType int mask) {
    public void setRequestedVisibleTypes(@InsetsType int visibleTypes, @InsetsType int mask) {
        final @InsetsType int requestedVisibleTypes =
        final @InsetsType int requestedVisibleTypes =
+5 −0
Original line number Original line Diff line number Diff line
@@ -232,6 +232,11 @@ public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner
    public void updateSurfacePosition(SparseArray<InsetsSourceControl> controls) {
    public void updateSurfacePosition(SparseArray<InsetsSourceControl> controls) {
    }
    }


    @Override
    public boolean willUpdateSurface() {
        return false;
    }

    @Override
    @Override
    public boolean hasZeroInsetsIme() {
    public boolean hasZeroInsetsIme() {
        return false;
        return false;
Loading