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

Commit 6dae2090 authored by Tiger Huang's avatar Tiger Huang Committed by Automerger Merge Worker
Browse files

Merge "Disable user animations on insets whose visible frame is empty" into...

Merge "Disable user animations on insets whose visible frame is empty" into rvc-dev am: ae9ce971 am: 07d77fce am: ad8e8926 am: 38cc421f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11754098

Change-Id: I0851d1c548670e0e8eec4b0ee0e82d295a5cd9d7
parents 15f327c9 38cc421f
Loading
Loading
Loading
Loading
+54 −2
Original line number Diff line number Diff line
@@ -485,6 +485,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    /** Set of inset types for which an animation was started since last resetting this field */
    private @InsetsType int mLastStartedAnimTypes;

    /** Set of inset types which cannot be controlled by the user animation */
    private @InsetsType int mLastDisabledUserAnimationInsetsTypes;

    private Runnable mInvokeControllableInsetsChangedListeners =
            this::invokeControllableInsetsChangedListeners;

    public InsetsController(Host host) {
        this(host, (controller, type) -> {
            if (type == ITYPE_IME) {
@@ -599,9 +605,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

    private void updateState(InsetsState newState) {
        mState.setDisplayFrame(newState.getDisplayFrame());
        @InsetsType int disabledUserAnimationTypes = 0;
        @InsetsType int[] cancelledUserAnimationTypes = {0};
        for (int i = newState.getSourcesCount() - 1; i >= 0; i--) {
            InsetsSource source = newState.sourceAt(i);
            getSourceConsumer(source.getType()).updateSource(source);
            @InternalInsetsType int internalInsetsType = source.getType();
            @AnimationType int animationType = getAnimationType(internalInsetsType);
            if (source.isVisibleFrameEmpty()) {
                @InsetsType int insetsType = toPublicType(internalInsetsType);
                // The user animation is not allowed when visible frame is empty.
                disabledUserAnimationTypes |= insetsType;
                if (animationType == ANIMATION_TYPE_USER) {
                    // Existing user animation needs to be cancelled.
                    animationType = ANIMATION_TYPE_NONE;
                    cancelledUserAnimationTypes[0] |= insetsType;
                }
            }
            getSourceConsumer(internalInsetsType).updateSource(source, animationType);
        }
        for (int i = mState.getSourcesCount() - 1; i >= 0; i--) {
            InsetsSource source = mState.sourceAt(i);
@@ -613,6 +633,27 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
                    mFrame.right, mFrame.top + mCaptionInsetsHeight));
        }

        updateDisabledUserAnimationTypes(disabledUserAnimationTypes);

        if (cancelledUserAnimationTypes[0] != 0) {
            mHandler.post(() -> show(cancelledUserAnimationTypes[0]));
        }
    }

    private void updateDisabledUserAnimationTypes(@InsetsType int disabledUserAnimationTypes) {
        @InsetsType int diff = mLastDisabledUserAnimationInsetsTypes ^ disabledUserAnimationTypes;
        if (diff != 0) {
            for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
                InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
                if (consumer.getControl() != null && (toPublicType(consumer.mType) & diff) != 0) {
                    mHandler.removeCallbacks(mInvokeControllableInsetsChangedListeners);
                    mHandler.post(mInvokeControllableInsetsChangedListeners);
                    break;
                }
            }
            mLastDisabledUserAnimationInsetsTypes = disabledUserAnimationTypes;
        }
    }

    private boolean captionInsetsUnchanged() {
@@ -896,6 +937,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        boolean imeReady = true;
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
            final InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i));
            if (animationType == ANIMATION_TYPE_USER) {
                final InsetsSource source = mState.peekSource(consumer.getType());
                if (source != null && source.isVisibleFrameEmpty()) {
                    if (WARN) Log.w(TAG, String.format(
                            "collectSourceControls can't run user animation for type: %s",
                            InsetsState.typeToString(consumer.getType())));
                    continue;
                }
            }
            boolean show = animationType == ANIMATION_TYPE_SHOW
                    || animationType == ANIMATION_TYPE_USER;
            boolean canRun = false;
@@ -1283,7 +1333,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        @InsetsType int result = 0;
        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
            InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
            if (consumer.getControl() != null) {
            InsetsSource source = mState.peekSource(consumer.mType);
            if (consumer.getControl() != null && source != null && !source.isVisibleFrameEmpty()) {
                result |= toPublicType(consumer.mType);
            }
        }
@@ -1294,6 +1345,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
     * @return The types that are now animating due to a listener invoking control/show/hide
     */
    private @InsetsType int invokeControllableInsetsChangedListeners() {
        mHandler.removeCallbacks(mInvokeControllableInsetsChangedListeners);
        mLastStartedAnimTypes = 0;
        @InsetsType int types = calculateControllableTypes();
        int size = mControllableInsetsChangedListeners.size();
+4 −0
Original line number Diff line number Diff line
@@ -92,6 +92,10 @@ public class InsetsSource implements Parcelable {
        return mVisible;
    }

    public boolean isVisibleFrameEmpty() {
        return mVisibleFrame != null && mVisibleFrame.isEmpty();
    }

    /**
     * Calculates the insets this source will cause to a client window.
     *
+3 −3
Original line number Diff line number Diff line
@@ -275,9 +275,9 @@ public class InsetsSourceConsumer {
    }

    @VisibleForTesting(visibility = PACKAGE)
    public void updateSource(InsetsSource newSource) {
    public void updateSource(InsetsSource newSource, @AnimationType int animationType) {
        InsetsSource source = mState.peekSource(mType);
        if (source == null || mController.getAnimationType(mType) == ANIMATION_TYPE_NONE
        if (source == null || animationType == ANIMATION_TYPE_NONE
                || source.getFrame().equals(newSource.getFrame())) {
            mPendingFrame = null;
            mPendingVisibleFrame = null;
@@ -286,7 +286,7 @@ public class InsetsSourceConsumer {
        }

        // Frame is changing while animating. Keep note of the new frame but keep existing frame
        // until animaition is finished.
        // until animation is finished.
        newSource = new InsetsSource(newSource);
        mPendingFrame = new Rect(newSource.getFrame());
        mPendingVisibleFrame = newSource.getVisibleFrame() != null
+4 −14
Original line number Diff line number Diff line
@@ -26,13 +26,11 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.app.Instrumentation;
import android.content.Context;
@@ -135,37 +133,29 @@ public class InsetsSourceConsumerTest {
        InsetsSourceConsumer consumer = new InsetsSourceConsumer(
                ITYPE_IME, state, null, controller);

        when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);

        InsetsSource source = new InsetsSource(ITYPE_IME);
        source.setFrame(0, 1, 2, 3);
        consumer.updateSource(new InsetsSource(source));

        when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER);
        consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_NONE);

        // While we're animating, updates are delayed
        source.setFrame(4, 5, 6, 7);
        consumer.updateSource(new InsetsSource(source));
        consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
        assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_IME).getFrame());

        // Finish the animation, now the pending frame should be applied
        when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
        assertTrue(consumer.notifyAnimationFinished());
        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());

        when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER);

        // Animating again, updates are delayed
        source.setFrame(8, 9, 10, 11);
        consumer.updateSource(new InsetsSource(source));
        consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());

        // Updating with the current frame triggers a different code path, verify this clears
        // the pending 8, 9, 10, 11 frame:
        source.setFrame(4, 5, 6, 7);
        consumer.updateSource(new InsetsSource(source));
        consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);

        when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
        assertFalse(consumer.notifyAnimationFinished());
        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
    }