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

Commit 3b0d1f9c authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Only play insets resize animation when needed" into 24D1-dev

parents 1cde6099 514f6576
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -737,15 +737,17 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

                @Override
                public void onIdMatch(InsetsSource source1, InsetsSource source2) {
                    final @InsetsType int type = source1.getType();
                    if ((type & Type.systemBars()) == 0
                    final Rect frame1 = source1.getFrame();
                    final Rect frame2 = source2.getFrame();
                    if (!source1.hasFlags(InsetsSource.FLAG_ANIMATE_RESIZING)
                            || !source2.hasFlags(InsetsSource.FLAG_ANIMATE_RESIZING)
                            || !source1.isVisible() || !source2.isVisible()
                            || source1.getFrame().equals(source2.getFrame())
                            || frame1.equals(frame2) || frame1.isEmpty() || frame2.isEmpty()
                            || !(Rect.intersects(mFrame, source1.getFrame())
                                    || Rect.intersects(mFrame, source2.getFrame()))) {
                        return;
                    }
                    mTypes |= type;
                    mTypes |= source1.getType();
                    if (mToState == null) {
                        mToState = new InsetsState();
                    }
@@ -877,7 +879,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            return false;
        }
        if (DEBUG) Log.d(TAG, "onStateChanged: " + state);
        mLastDispatchedState.set(state, true /* copySources */);

        final InsetsState lastState = new InsetsState(mState, true /* copySources */);
        updateState(state);
@@ -888,10 +889,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                true /* excludesInvisibleIme */)) {
            if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
            mHost.notifyInsetsChanged();
            if (lastState.getDisplayFrame().equals(mState.getDisplayFrame())) {
                InsetsState.traverse(lastState, mState, mStartResizingAnimationIfNeeded);
            if (mLastDispatchedState.getDisplayFrame().equals(state.getDisplayFrame())) {
                // Here compares the raw states instead of the overridden ones because we don't want
                // to animate an insets source that its mServerVisible is false.
                InsetsState.traverse(mLastDispatchedState, state, mStartResizingAnimationIfNeeded);
            }
        }
        mLastDispatchedState.set(state, true /* copySources */);
        return true;
    }

+9 −0
Original line number Diff line number Diff line
@@ -99,11 +99,17 @@ public class InsetsSource implements Parcelable {
     */
    public static final int FLAG_FORCE_CONSUMING = 1 << 2;

    /**
     * Controls whether the insets source will play an animation when resizing.
     */
    public static final int FLAG_ANIMATE_RESIZING = 1 << 3;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = "FLAG_", value = {
            FLAG_SUPPRESS_SCRIM,
            FLAG_INSETS_ROUNDED_CORNER,
            FLAG_FORCE_CONSUMING,
            FLAG_ANIMATE_RESIZING,
    })
    public @interface Flags {}

@@ -540,6 +546,9 @@ public class InsetsSource implements Parcelable {
        if ((flags & FLAG_FORCE_CONSUMING) != 0) {
            joiner.add("FORCE_CONSUMING");
        }
        if ((flags & FLAG_ANIMATE_RESIZING) != 0) {
            joiner.add("ANIMATE_RESIZING");
        }
        return joiner.toString();
    }

+63 −19
Original line number Diff line number Diff line
@@ -21,12 +21,11 @@ import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_RESIZE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsController.AnimationType;
import static android.view.InsetsSource.FLAG_ANIMATE_RESIZING;
import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
import static android.view.WindowInsets.Type.SIZE;
import static android.view.WindowInsets.Type.all;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.defaultVisible;
@@ -671,36 +670,81 @@ public class InsetsControllerTest {
    }

    @Test
    public void testResizeAnimation_insetsTypes() {
        for (int i = 0; i < SIZE; i++) {
            final @InsetsType int type = 1 << i;
            final @AnimationType int expectedAnimationType = (type & systemBars()) != 0
                            ? ANIMATION_TYPE_RESIZE
                            : ANIMATION_TYPE_NONE;
            doTestResizeAnimation_insetsTypes(type, expectedAnimationType);
        }
    public void testResizeAnimation_withFlagAnimateResizing() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            final int id = ID_NAVIGATION_BAR;
            final @InsetsType int type = navigationBars();
            final InsetsState state1 = new InsetsState();
            state1.getOrCreateSource(id, type)
                    .setVisible(true)
                    .setFrame(0, 0, 500, 50)
                    .setFlags(FLAG_ANIMATE_RESIZING, FLAG_ANIMATE_RESIZING);
            final InsetsState state2 = new InsetsState(state1, true /* copySources */);
            state2.peekSource(id).setFrame(0, 0, 500, 60);

            // New insets source won't cause the resize animation.
            mController.onStateChanged(state1);
            assertEquals("There must not be resize animation.", ANIMATION_TYPE_NONE,
                    mController.getAnimationType(type));

            // Changing frame of the source with FLAG_ANIMATE_RESIZING will cause the resize
            // animation.
            mController.onStateChanged(state2);
            assertEquals("There must be resize animation.", ANIMATION_TYPE_RESIZE,
                    mController.getAnimationType(type));
        });
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    }

    private void doTestResizeAnimation_insetsTypes(@InsetsType int type,
            @AnimationType int expectedAnimationType) {
        final int id = type;
    @Test
    public void testResizeAnimation_withoutFlagAnimateResizing() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            final int id = ID_STATUS_BAR;
            final @InsetsType int type = statusBars();
            final InsetsState state1 = new InsetsState();
            state1.getOrCreateSource(id, type).setVisible(true).setFrame(0, 0, 500, 50);
            state1.getOrCreateSource(id, type)
                    .setVisible(true)
                    .setFrame(0, 0, 500, 50)
                    .setFlags(0, FLAG_ANIMATE_RESIZING);
            final InsetsState state2 = new InsetsState(state1, true /* copySources */);
            state2.peekSource(id).setFrame(0, 0, 500, 60);
            final String message = "Animation type of " + WindowInsets.Type.toString(type) + ":";
            final String message = "There must not be resize animation.";

            // New insets source won't cause the resize animation.
            mController.onStateChanged(state1);
            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));

            // Changing frame of the source without FLAG_ANIMATE_RESIZING must not cause the resize
            // animation.
            mController.onStateChanged(state2);
            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
        });
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    }

    @Test
    public void testResizeAnimation_sourceFrame() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            final int id = ID_STATUS_BAR;
            final @InsetsType int type = statusBars();
            final InsetsState state1 = new InsetsState();
            state1.setDisplayFrame(new Rect(0, 0, 500, 1000));
            state1.getOrCreateSource(id, type).setFrame(0, 0, 500, 50);
            final InsetsState state2 = new InsetsState(state1, true /* copySources */);
            state2.setDisplayFrame(state1.getDisplayFrame());
            state2.peekSource(id).setFrame(0, 0, 500, 0);
            final String message = "There must not be resize animation.";

            // New insets source won't cause the resize animation.
            mController.onStateChanged(state1);
            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));

            // Changing frame might cause the resize animation. This depends on the insets type.
            // Changing frame won't cause the resize animation if the new frame is empty.
            mController.onStateChanged(state2);
            assertEquals(message, expectedAnimationType, mController.getAnimationType(type));
            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));

            // Cancel the existing animations for the next iteration.
            mController.cancelExistingAnimations();
            // Changing frame won't cause the resize animation if the existing frame is empty.
            mController.onStateChanged(state1);
            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
        });
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();