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

Commit 33c0e9ce authored by Joshua Tsuji's avatar Joshua Tsuji
Browse files

Don't animate new bubbles in until the stack pos is set.

Test: atest SystemUITests
Bug: 132782486
Change-Id: Ie6879de845dc1acb4fc5ee467e2384407394d345
parent a34308ca
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -86,7 +86,10 @@ public class StackAnimationController extends
     * we need to keep track of it separately from the first bubble's translation in case there are
     * no bubbles, or the first bubble was just added and being animated to its new position.
     */
    private PointF mStackPosition = new PointF();
    private PointF mStackPosition = new PointF(-1, -1);

    /** Whether or not the stack's start position has been set. */
    private boolean mStackMovedToStartPosition = false;

    /** The most recent position in which the stack was resting on the edge of the screen. */
    private PointF mRestingStackPosition;
@@ -193,9 +196,10 @@ public class StackAnimationController extends

    /** Whether the stack is on the left side of the screen. */
    public boolean isStackOnLeftSide() {
        if (mLayout == null) {
        if (mLayout == null || !isStackPositionSet()) {
            return false;
        }

        float stackCenter = mStackPosition.x + mIndividualBubbleSize / 2;
        float screenCenter = mLayout.getWidth() / 2;
        return stackCenter < screenCenter;
@@ -630,10 +634,9 @@ public class StackAnimationController extends
    @Override
    void onChildAdded(View child, int index) {
        if (mLayout.getChildCount() == 1) {
            // If this is the first child added, position the stack in its starting position before
            // animating in.
            moveStackToStartPosition(() -> animateInBubble(child));
        } else if (mLayout.indexOfChild(child) == 0) {
            // If this is the first child added, position the stack in its starting position.
            moveStackToStartPosition();
        } else if (isStackPositionSet() && mLayout.indexOfChild(child) == 0) {
            // Otherwise, animate the bubble in if it's the newest bubble. If we're adding a bubble
            // to the back of the stack, it'll be largely invisible so don't bother animating it in.
            animateInBubble(child);
@@ -657,16 +660,21 @@ public class StackAnimationController extends
    }

    /** Moves the stack, without any animation, to the starting position. */
    private void moveStackToStartPosition(Runnable after) {
    private void moveStackToStartPosition() {
        // Post to ensure that the layout's width and height have been calculated.
        mLayout.setVisibility(View.INVISIBLE);
        mLayout.post(() -> {
            mStackMovedToStartPosition = true;
            setStackPosition(
                    mRestingStackPosition == null
                            ? getDefaultStartPosition()
                            : mRestingStackPosition);
            mLayout.setVisibility(View.VISIBLE);
            after.run();

            // Animate in the top bubble now that we're visible.
            if (mLayout.getChildCount() > 0) {
                animateInBubble(mLayout.getChildAt(0));
            }
        });
    }

@@ -718,6 +726,10 @@ public class StackAnimationController extends
                getAllowableStackPositionRegion().top + mStackStartingVerticalOffset);
    }

    private boolean isStackPositionSet() {
        return mStackMovedToStartPosition;
    }

    /** Animates in the given bubble. */
    private void animateInBubble(View child) {
        child.setTranslationY(mStackPosition.y);
+10 −0
Original line number Diff line number Diff line
@@ -137,6 +137,16 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
            super(context);
        }

        @Override
        public boolean post(Runnable action) {
            return mMainThreadHandler.post(action);
        }

        @Override
        public boolean postDelayed(Runnable action, long delayMillis) {
            return mMainThreadHandler.postDelayed(action, delayMillis);
        }

        @Override
        public void setController(PhysicsAnimationController controller) {
            runOnMainThreadAndBlock(
+29 −1
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@ import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Spy;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@SmallTest
@RunWith(AndroidTestingRunner.class)
public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase {
@@ -46,12 +49,13 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
    private TestableStackController mStackController = new TestableStackController();

    private int mStackOffset;
    private Runnable mCheckStartPosSet;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        addOneMoreThanRenderLimitBubbles();
        mLayout.setController(mStackController);
        addOneMoreThanRenderLimitBubbles();
        mStackOffset = mLayout.getResources().getDimensionPixelSize(R.dimen.bubble_stack_offset);
    }

@@ -166,6 +170,8 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
                0,
                new FrameLayout.LayoutParams(50, 50));

        waitForStartPosToBeSet();
        waitForLayoutMessageQueue();
        waitForPropertyAnimations(
                DynamicAnimation.TRANSLATION_X,
                DynamicAnimation.TRANSLATION_Y,
@@ -293,6 +299,28 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
        }
    }

    /** Waits up to 2 seconds for the initial stack position to be initialized. */
    private void waitForStartPosToBeSet() throws InterruptedException {
        final CountDownLatch animLatch = new CountDownLatch(1);

        mCheckStartPosSet = () -> {
            if (mStackController.getStackPosition().x >= 0) {
                animLatch.countDown();
            } else {
                mMainThreadHandler.post(mCheckStartPosSet);
            }
        };

        mMainThreadHandler.post(mCheckStartPosSet);

        try {
            animLatch.await(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            mMainThreadHandler.removeCallbacks(mCheckStartPosSet);
            throw e;
        }
    }

    /**
     * Testable version of the stack controller that dispatches its animations on the main thread.
     */