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

Commit ec60ab15 authored by Josh Tsuji's avatar Josh Tsuji Committed by Automerger Merge Worker
Browse files

Merge "Remove Bubbles from the WM, only after all bubbles finish animating...

Merge "Remove Bubbles from the WM, only after all bubbles finish animating out." into rvc-dev am: e7b00f67

Change-Id: Ia8fb4b5dbe3cffb76f7e5c4fc4dff4586b9a7f67
parents 0660f710 e7b00f67
Loading
Loading
Loading
Loading
+72 −16
Original line number Diff line number Diff line
@@ -185,9 +185,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
    // Used to post to main UI thread
    private Handler mHandler = new Handler();

    /** LayoutParams used to add the BubbleStackView to the window maanger. */
    /** LayoutParams used to add the BubbleStackView to the window manager. */
    private WindowManager.LayoutParams mWmLayoutParams;

    /** Whether or not the BubbleStackView has been added to the WindowManager. */
    private boolean mAddedToWindowManager = false;

    // Used for determining view rect for touch interaction
    private Rect mTempRect = new Rect();
@@ -595,9 +596,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        if (mStackView == null) {
            mStackView = new BubbleStackView(
                    mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
                    mSysUiState, mNotificationShadeWindowController);
                    mSysUiState, mNotificationShadeWindowController, this::onAllBubblesAnimatedOut);
            mStackView.addView(mBubbleScrim);
            addToWindowManager();
            if (mExpandListener != null) {
                mStackView.setExpandListener(mExpandListener);
            }
@@ -605,10 +605,17 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
            mStackView.setUnbubbleConversationCallback(notificationEntry ->
                    onUserChangedBubble(notificationEntry, false /* shouldBubble */));
        }

        addToWindowManagerMaybe();
    }

    /** Adds the BubbleStackView to the WindowManager if it's not already there. */
    private void addToWindowManagerMaybe() {
        // If the stack is null, or already added, don't add it.
        if (mStackView == null || mAddedToWindowManager) {
            return;
        }

    /** Adds the BubbleStackView to the WindowManager. */
    private void addToWindowManager() {
        mWmLayoutParams = new WindowManager.LayoutParams(
                // Fill the screen so we can use translation animations to position the bubble
                // stack. We'll use touchable regions to ignore touches that are not on the bubbles
@@ -629,9 +636,37 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        mWmLayoutParams.packageName = mContext.getPackageName();
        mWmLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

        try {
            mAddedToWindowManager = true;
            mWindowManager.addView(mStackView, mWmLayoutParams);
        } catch (IllegalStateException e) {
            // This means the stack has already been added. This shouldn't happen, since we keep
            // track of that, but just in case, update the previously added view's layout params.
            e.printStackTrace();
            updateWmFlags();
        }
    }

    /** Removes the BubbleStackView from the WindowManager if it's there. */
    private void removeFromWindowManagerMaybe() {
        if (!mAddedToWindowManager) {
            return;
        }

        try {
            mAddedToWindowManager = false;
            mWindowManager.removeView(mStackView);
        } catch (IllegalArgumentException e) {
            // This means the stack has already been removed - it shouldn't happen, but ignore if it
            // does, since we wanted it removed anyway.
            e.printStackTrace();
        }
    }

    /**
     * Updates the BubbleStackView's WindowManager.LayoutParams, and updates the WindowManager with
     * the new params if the stack has been added.
     */
    private void updateWmFlags() {
        if (isStackExpanded()) {
            // If we're expanded, we want to be focusable so that the ActivityView can receive focus
@@ -643,7 +678,25 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
            mWmLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        }

        if (mStackView != null && mAddedToWindowManager) {
            try {
                mWindowManager.updateViewLayout(mStackView, mWmLayoutParams);
            } catch (IllegalArgumentException e) {
                // If the stack is somehow not there, ignore the attempt to update it.
                e.printStackTrace();
            }
        }
    }

    /**
     * Called by the BubbleStackView and whenever all bubbles have animated out, and none have been
     * added in the meantime.
     */
    private void onAllBubblesAnimatedOut() {
        if (mStackView != null) {
            mStackView.setVisibility(INVISIBLE);
            removeFromWindowManagerMaybe();
        }
    }

    /**
@@ -833,10 +886,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
    }

    void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
        if (mStackView == null) {
        // Lazy init stack view when a bubble is created
        ensureStackViewCreated();
        }

        // If this is an interruptive notif, mark that it's interrupted
        if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) {
            notif.setInterruption();
@@ -1196,11 +1248,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        if (mStackView == null) {
            return;
        }
        if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) {
            // Bubbles only appear in unlocked shade
            mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE);
        } else if (mStackView != null) {

        if (mStatusBarStateListener.getCurrentState() != SHADE) {
            // Bubbles don't appear over the locked shade.
            mStackView.setVisibility(INVISIBLE);
        } else if (hasBubbles()) {
            // If we're unlocked, show the stack if we have bubbles. If we don't have bubbles, the
            // stack will be set to INVISIBLE in onAllBubblesAnimatedOut after the bubbles animate
            // out.
            mStackView.setVisibility(VISIBLE);
        }

        mStackView.updateContentDescription();
+11 −3
Original line number Diff line number Diff line
@@ -656,7 +656,8 @@ public class BubbleStackView extends FrameLayout
            @Nullable SurfaceSynchronizer synchronizer,
            FloatingContentCoordinator floatingContentCoordinator,
            SysUiState sysUiState,
            NotificationShadeWindowController notificationShadeWindowController) {
            NotificationShadeWindowController notificationShadeWindowController,
            Runnable allBubblesAnimatedOutAction) {
        super(context);

        mBubbleData = data;
@@ -691,11 +692,18 @@ public class BubbleStackView extends FrameLayout
        mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
        int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);

        final Runnable onBubbleAnimatedOut = () -> {
            if (getBubbleCount() == 0) {
                allBubblesAnimatedOutAction.run();
            }
        };

        mStackAnimationController = new StackAnimationController(
                floatingContentCoordinator, this::getBubbleCount);
                floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut);

        mExpandedAnimationController = new ExpandedAnimationController(
                mDisplaySize, mExpandedViewPadding, res.getConfiguration().orientation);
                mDisplaySize, mExpandedViewPadding, res.getConfiguration().orientation,
                onBubbleAnimatedOut);
        mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;

        setUpUserEducation();
+21 −10
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import androidx.dynamicanimation.animation.SpringForce;

import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.util.animation.PhysicsAnimator;
import com.android.systemui.util.magnetictarget.MagnetizedObject;

import com.google.android.collect.Sets;
@@ -69,6 +70,10 @@ public class ExpandedAnimationController
     */
    private static final float FLING_TO_DISMISS_MIN_VELOCITY = 6000f;

    private final PhysicsAnimator.SpringConfig mAnimateOutSpringConfig =
            new PhysicsAnimator.SpringConfig(
                    EXPAND_COLLAPSE_ANIM_STIFFNESS, SpringForce.DAMPING_RATIO_NO_BOUNCY);

    /** Horizontal offset between bubbles, which we need to know to re-stack them. */
    private float mStackOffsetPx;
    /** Space between status bar and bubbles in the expanded state. */
@@ -116,10 +121,17 @@ public class ExpandedAnimationController

    private int mExpandedViewPadding;

    /**
     * Callback to run whenever any bubble is animated out. The BubbleStackView will check if the
     * end of this animation means we have no bubbles left, and notify the BubbleController.
     */
    private Runnable mOnBubbleAnimatedOutAction;

    public ExpandedAnimationController(Point displaySize, int expandedViewPadding,
            int orientation) {
            int orientation, Runnable onBubbleAnimatedOutAction) {
        updateResources(orientation, displaySize);
        mExpandedViewPadding = expandedViewPadding;
        mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
    }

    /**
@@ -355,8 +367,8 @@ public class ExpandedAnimationController
        }
        animationForChild(bubble)
                .withStiffness(SpringForce.STIFFNESS_HIGH)
                .scaleX(1.1f)
                .scaleY(1.1f)
                .scaleX(0f)
                .scaleY(0f)
                .translationY(bubble.getTranslationY() + translationYBy)
                .alpha(0f, after)
                .start();
@@ -500,18 +512,17 @@ public class ExpandedAnimationController

    @Override
    void onChildRemoved(View child, int index, Runnable finishRemoval) {
        final PhysicsAnimationLayout.PhysicsPropertyAnimator animator = animationForChild(child);

        // If we're removing the dragged-out bubble, that means it got dismissed.
        if (child.equals(getDraggedOutBubble())) {
            mMagnetizedBubbleDraggingOut = null;
            finishRemoval.run();
            mOnBubbleAnimatedOutAction.run();
        } else {
            animator.alpha(0f, finishRemoval /* endAction */)
                    .withStiffness(SpringForce.STIFFNESS_HIGH)
                    .withDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)
                    .scaleX(1.1f)
                    .scaleY(1.1f)
            PhysicsAnimator.getInstance(child)
                    .spring(DynamicAnimation.ALPHA, 0f)
                    .spring(DynamicAnimation.SCALE_X, 0f, mAnimateOutSpringConfig)
                    .spring(DynamicAnimation.SCALE_Y, 0f, mAnimateOutSpringConfig)
                    .withEndActions(finishRemoval, mOnBubbleAnimatedOutAction)
                    .start();
        }

+20 −11
Original line number Diff line number Diff line
@@ -74,6 +74,10 @@ public class StackAnimationController extends
    private static final int FLING_FOLLOW_STIFFNESS = 20000;
    public static final float DEFAULT_BOUNCINESS = 0.9f;

    private final PhysicsAnimator.SpringConfig mAnimateOutSpringConfig =
            new PhysicsAnimator.SpringConfig(
                    ANIMATE_IN_STIFFNESS, SpringForce.DAMPING_RATIO_NO_BOUNCY);

    /**
     * Friction applied to fling animations. Since the stack must land on one of the sides of the
     * screen, we want less friction horizontally so that the stack has a better chance of making it
@@ -248,12 +252,19 @@ public class StackAnimationController extends
    /** Returns the number of 'real' bubbles (excluding the overflow bubble). */
    private IntSupplier mBubbleCountSupplier;

    /**
     * Callback to run whenever any bubble is animated out. The BubbleStackView will check if the
     * end of this animation means we have no bubbles left, and notify the BubbleController.
     */
    private Runnable mOnBubbleAnimatedOutAction;

    public StackAnimationController(
            FloatingContentCoordinator floatingContentCoordinator,
            IntSupplier bubbleCountSupplier) {
            IntSupplier bubbleCountSupplier,
            Runnable onBubbleAnimatedOutAction) {
        mFloatingContentCoordinator = floatingContentCoordinator;
        mBubbleCountSupplier = bubbleCountSupplier;

        mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
    }

    /**
@@ -652,8 +663,8 @@ public class StackAnimationController extends
    public void animateStackDismissal(float translationYBy, Runnable after) {
        animationsForChildrenFromIndex(0, (index, animation) ->
                animation
                        .scaleX(0.5f)
                        .scaleY(0.5f)
                        .scaleX(0f)
                        .scaleY(0f)
                        .alpha(0f)
                        .translationY(
                                mLayout.getChildAt(index).getTranslationY() + translationYBy)
@@ -760,13 +771,11 @@ public class StackAnimationController extends

    @Override
    void onChildRemoved(View child, int index, Runnable finishRemoval) {
        // Animate the removing view in the opposite direction of the stack.
        final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
        animationForChild(child)
                .alpha(0f, finishRemoval /* after */)
                .scaleX(ANIMATE_IN_STARTING_SCALE)
                .scaleY(ANIMATE_IN_STARTING_SCALE)
                .translationX(mStackPosition.x - (-xOffset * ANIMATE_TRANSLATION_FACTOR))
        PhysicsAnimator.getInstance(child)
                .spring(DynamicAnimation.ALPHA, 0f)
                .spring(DynamicAnimation.SCALE_X, 0f, mAnimateOutSpringConfig)
                .spring(DynamicAnimation.SCALE_Y, 0f, mAnimateOutSpringConfig)
                .withEndActions(finishRemoval, mOnBubbleAnimatedOutAction)
                .start();

        // If there are other bubbles, pull them into the correct position.
+3 −1
Original line number Diff line number Diff line
@@ -49,11 +49,13 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
    private int mOrientation = Configuration.ORIENTATION_PORTRAIT;
    private float mLauncherGridDiff = 30f;

    private Runnable mOnBubbleAnimatedOutAction = Mockito.mock(Runnable.class);

    @Spy
    private ExpandedAnimationController mExpandedController =
            new ExpandedAnimationController(
                    new Point(mDisplayWidth, mDisplayHeight) /* displaySize */,
                    mExpandedViewPadding, mOrientation);
                    mExpandedViewPadding, mOrientation, mOnBubbleAnimatedOutAction);

    private int mStackOffset;
    private float mBubblePaddingTop;
Loading