resolve merge conflicts of 65cba0fa324f610923b4b88709ebdb9128ec5dcd to qt-r1-bubbles-dev
Bug: None
Test: atest SystemUITests
Change-Id: I7194279a6a273cc97353857dadf73d413c7c9580
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 560e264..40fb6d2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -330,9 +330,7 @@
mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
mBubbleContainer = new PhysicsAnimationLayout(context);
- mBubbleContainer.setMaxRenderedChildren(
- getResources().getInteger(R.integer.bubbles_max_rendered));
- mBubbleContainer.setController(mStackAnimationController);
+ mBubbleContainer.setActiveController(mStackAnimationController);
mBubbleContainer.setElevation(elevation);
mBubbleContainer.setClipChildren(false);
addView(mBubbleContainer, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
@@ -728,7 +726,7 @@
public void updateBubbleOrder(List<Bubble> bubbles) {
for (int i = 0; i < bubbles.size(); i++) {
Bubble bubble = bubbles.get(i);
- mBubbleContainer.moveViewTo(bubble.iconView, i);
+ mBubbleContainer.reorderView(bubble.iconView, i);
}
}
@@ -905,8 +903,10 @@
mBubbleContainer.cancelAllAnimations();
mExpandedAnimationController.collapseBackToStack(
+ mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
+ /* collapseTo */,
() -> {
- mBubbleContainer.setController(mStackAnimationController);
+ mBubbleContainer.setActiveController(mStackAnimationController);
afterExpandedViewAnimation();
});
@@ -921,14 +921,11 @@
mIsExpanded = true;
beforeExpandedViewAnimation();
- mBubbleContainer.setController(mExpandedAnimationController);
- mExpandedAnimationController.expandFromStack(
- mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
- /* collapseTo */,
- () -> {
- updatePointerPosition();
- afterExpandedViewAnimation();
- } /* after */);
+ mBubbleContainer.setActiveController(mExpandedAnimationController);
+ mExpandedAnimationController.expandFromStack(() -> {
+ updatePointerPosition();
+ afterExpandedViewAnimation();
+ } /* after */);
mExpandedViewContainer.setTranslationX(getCollapsedX());
@@ -1017,7 +1014,7 @@
}
mStackAnimationController.cancelStackPositionAnimations();
- mBubbleContainer.setController(mStackAnimationController);
+ mBubbleContainer.setActiveController(mStackAnimationController);
hideFlyoutImmediate();
mDraggingInDismissTarget = false;
@@ -1115,6 +1112,10 @@
/** Called when a gesture is completed or cancelled. */
void onGestureFinished() {
mIsGestureInProgress = false;
+
+ if (mIsExpanded) {
+ mExpandedAnimationController.onGestureFinished();
+ }
}
/** Prepares and starts the desaturate/darken animation on the bubble stack. */
@@ -1205,6 +1206,7 @@
*/
void magnetToStackIfNeededThenAnimateDismissal(
View touchedView, float velX, float velY, Runnable after) {
+ final View draggedOutBubble = mExpandedAnimationController.getDraggedOutBubble();
final Runnable animateDismissal = () -> {
mAfterMagnet = null;
@@ -1222,7 +1224,7 @@
resetDesaturationAndDarken();
});
} else {
- mExpandedAnimationController.dismissDraggedOutBubble(() -> {
+ mExpandedAnimationController.dismissDraggedOutBubble(draggedOutBubble, () -> {
mAnimatingMagnet = false;
mShowingDismiss = false;
mDraggingInDismissTarget = false;
@@ -1389,10 +1391,18 @@
};
// Post in case layout isn't complete and getWidth returns 0.
- post(() -> mFlyout.showFlyout(
- updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
- mStackAnimationController.isStackOnLeftSide(),
- bubble.iconView.getBadgeColor(), mAfterFlyoutHides));
+ post(() -> {
+ // An auto-expanding bubble could have been posted during the time it takes to
+ // layout.
+ if (isExpanded()) {
+ return;
+ }
+
+ mFlyout.showFlyout(
+ updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
+ mStackAnimationController.isStackOnLeftSide(),
+ bubble.iconView.getBadgeColor(), mAfterFlyoutHides);
+ });
}
mFlyout.removeCallbacks(mHideFlyout);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index c5fe91c..f111f04 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -22,6 +22,7 @@
import android.view.View;
import android.view.WindowInsets;
+import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@@ -67,6 +68,12 @@
/** Whether the dragged-out bubble is in the dismiss target. */
private boolean mIndividualBubbleWithinDismissTarget = false;
+ private boolean mAnimatingExpand = false;
+ private boolean mAnimatingCollapse = false;
+ private Runnable mAfterExpand;
+ private Runnable mAfterCollapse;
+ private PointF mCollapsePoint;
+
/**
* Whether the dragged out bubble is springing towards the touch point, rather than using the
* default behavior of moving directly to the touch point.
@@ -94,49 +101,61 @@
/** The bubble currently being dragged out of the row (to potentially be dismissed). */
private View mBubbleDraggingOut;
- @Override
- protected void setLayout(PhysicsAnimationLayout layout) {
- super.setLayout(layout);
-
- final Resources res = layout.getResources();
- mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
- mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
- }
-
/**
* Animates expanding the bubbles into a row along the top of the screen.
*/
- public void expandFromStack(PointF collapseTo, Runnable after) {
- animationsForChildrenFromIndex(
- 0, /* startIndex */
- new ChildAnimationConfigurator() {
- @Override
- public void configureAnimationForChildAtIndex(
- int index, PhysicsAnimationLayout.PhysicsPropertyAnimator animation) {
- animation.position(getBubbleLeft(index), getExpandedY());
- }
- })
- .startAll(after);
+ public void expandFromStack(Runnable after) {
+ mAnimatingCollapse = false;
+ mAnimatingExpand = true;
+ mAfterExpand = after;
- mCollapseToPoint = collapseTo;
+ startOrUpdateExpandAnimation();
}
/** Animate collapsing the bubbles back to their stacked position. */
- public void collapseBackToStack(Runnable after) {
- // Stack to the left if we're going to the left, or right if not.
- final float sideMultiplier = mLayout.isFirstChildXLeftOfCenter(mCollapseToPoint.x) ? -1 : 1;
+ public void collapseBackToStack(PointF collapsePoint, Runnable after) {
+ mAnimatingExpand = false;
+ mAnimatingCollapse = true;
+ mAfterCollapse = after;
+ mCollapsePoint = collapsePoint;
+ startOrUpdateCollapseAnimation();
+ }
+
+ private void startOrUpdateExpandAnimation() {
animationsForChildrenFromIndex(
0, /* startIndex */
- (index, animation) ->
+ (index, animation) -> animation.position(getBubbleLeft(index), getExpandedY()))
+ .startAll(() -> {
+ mAnimatingExpand = false;
+
+ if (mAfterExpand != null) {
+ mAfterExpand.run();
+ }
+
+ mAfterExpand = null;
+ });
+ }
+
+ private void startOrUpdateCollapseAnimation() {
+ // Stack to the left if we're going to the left, or right if not.
+ final float sideMultiplier = mLayout.isFirstChildXLeftOfCenter(mCollapsePoint.x) ? -1 : 1;
+ animationsForChildrenFromIndex(
+ 0, /* startIndex */
+ (index, animation) -> {
animation.position(
- mCollapseToPoint.x + (sideMultiplier * index * mStackOffsetPx),
- mCollapseToPoint.y))
- .startAll(after /* endAction */);
+ mCollapsePoint.x + (sideMultiplier * index * mStackOffsetPx),
+ mCollapsePoint.y);
+ })
+ .startAll(() -> {
+ mAnimatingCollapse = false;
+
+ if (mAfterCollapse != null) {
+ mAfterCollapse.run();
+ }
+
+ mAfterCollapse = null;
+ });
}
/** Prepares the given bubble to be dragged out. */
@@ -180,10 +199,10 @@
}
/** Plays a dismiss animation on the dragged out bubble. */
- public void dismissDraggedOutBubble(Runnable after) {
+ public void dismissDraggedOutBubble(View bubble, Runnable after) {
mIndividualBubbleWithinDismissTarget = false;
- animationForChild(mBubbleDraggingOut)
+ animationForChild(bubble)
.withStiffness(SpringForce.STIFFNESS_HIGH)
.scaleX(1.1f)
.scaleY(1.1f)
@@ -193,6 +212,10 @@
updateBubblePositions();
}
+ @Nullable public View getDraggedOutBubble() {
+ return mBubbleDraggingOut;
+ }
+
/** Magnets the given bubble to the dismiss target. */
public void magnetBubbleToDismiss(
View bubbleView, float velX, float velY, float destY, Runnable after) {
@@ -231,21 +254,18 @@
final int index = mLayout.indexOfChild(bubbleView);
animationForChildAtIndex(index)
- .position(getBubbleLeft(index), getExpandedY())
- .withPositionStartVelocities(velX, velY)
- .start(() -> bubbleView.setTranslationZ(0f) /* after */);
+ .position(getBubbleLeft(index), getExpandedY())
+ .withPositionStartVelocities(velX, velY)
+ .start(() -> bubbleView.setTranslationZ(0f) /* after */);
- mBubbleDraggingOut = null;
- mBubbleDraggedOutEnough = false;
updateBubblePositions();
}
- /**
- * Sets configuration variables.
- */
- public void prepareForDismissalWithVelocity(View bubbleView) {
- mBubbleDraggingOut = bubbleView;
+ /** Resets bubble drag out gesture flags. */
+ public void onGestureFinished() {
mBubbleDraggedOutEnough = false;
+ mBubbleDraggingOut = null;
+ updateBubblePositions();
}
/**
@@ -271,6 +291,23 @@
}
@Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
+ final Resources res = layout.getResources();
+ mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
+ mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
+ mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mStatusBarHeight =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
+
+ // Ensure that all child views are at 1x scale, and visible, in case they were animating
+ // in.
+ mLayout.setVisibility(View.VISIBLE);
+ animationsForChildrenFromIndex(0 /* startIndex */, (index, animation) ->
+ animation.scaleX(1f).scaleY(1f).alpha(1f)).startAll();
+ }
+
+ @Override
Set<DynamicAnimation.ViewProperty> getAnimatedProperties() {
return Sets.newHashSet(
DynamicAnimation.TRANSLATION_X,
@@ -299,12 +336,21 @@
@Override
void onChildAdded(View child, int index) {
- animationForChild(child)
- .translationY(
- getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */
- getExpandedY() /* to */)
- .start();
- updateBubblePositions();
+ // If a bubble is added while the expand/collapse animations are playing, update the
+ // animation to include the new bubble.
+ if (mAnimatingExpand) {
+ startOrUpdateExpandAnimation();
+ } else if (mAnimatingCollapse) {
+ startOrUpdateCollapseAnimation();
+ } else {
+ child.setTranslationX(getBubbleLeft(index));
+ animationForChild(child)
+ .translationY(
+ getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */
+ getExpandedY() /* to */)
+ .start();
+ updateBubblePositions();
+ }
}
@Override
@@ -329,19 +375,15 @@
}
@Override
- protected void setChildVisibility(View child, int index, int visibility) {
- if (visibility == View.VISIBLE) {
- // Set alpha to 0 but then become visible immediately so the animation is visible.
- child.setAlpha(0f);
- child.setVisibility(View.VISIBLE);
- }
-
- animationForChild(child)
- .alpha(visibility == View.GONE ? 0f : 1f)
- .start(() -> super.setChildVisibility(child, index, visibility) /* after */);
+ void onChildReordered(View child, int oldIndex, int newIndex) {
+ updateBubblePositions();
}
private void updateBubblePositions() {
+ if (mAnimatingExpand || mAnimatingCollapse) {
+ return;
+ }
+
for (int i = 0; i < mLayout.getChildCount(); i++) {
final View bubble = mLayout.getChildAt(i);
@@ -350,6 +392,7 @@
if (bubble.equals(mBubbleDraggingOut)) {
return;
}
+
animationForChild(bubble)
.translationX(getBubbleLeft(i))
.start();
@@ -371,10 +414,6 @@
}
int bubbleCount = mLayout.getChildCount();
- if (bubbleCount > mBubblesMaxRendered) {
- // Only rendered bubbles are relevant for calculating row left.
- bubbleCount = mBubblesMaxRendered;
- }
final float totalBubbleWidth = bubbleCount * mBubbleSizePx;
final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
index 997d2c4..3a33392 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
@@ -17,10 +17,12 @@
package com.android.systemui.bubbles.animation;
import android.content.Context;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@@ -137,12 +139,33 @@
*/
abstract void onChildRemoved(View child, int index, Runnable finishRemoval);
+ /** Called when a child view has been reordered in the view hierachy. */
+ abstract void onChildReordered(View child, int oldIndex, int newIndex);
+
+ /**
+ * Called when the controller is set as the active animation controller for the given
+ * layout. Once active, the controller can start animations using the animator instances
+ * returned by {@link #animationForChild}.
+ *
+ * While all animations started by the previous controller will be cancelled, the new
+ * controller should not make any assumptions about the state of the layout or its children.
+ * Their translation, alpha, scale, etc. values may have been changed by the previous
+ * controller and should be reset here if relevant.
+ */
+ abstract void onActiveControllerForLayout(PhysicsAnimationLayout layout);
+
protected PhysicsAnimationLayout mLayout;
PhysicsAnimationController() { }
+ /** Whether this controller is the currently active controller for its associated layout. */
+ protected boolean isActiveController() {
+ return this == mLayout.mController;
+ }
+
protected void setLayout(PhysicsAnimationLayout layout) {
this.mLayout = layout;
+ onActiveControllerForLayout(layout);
}
protected PhysicsAnimationLayout getLayout() {
@@ -150,15 +173,6 @@
}
/**
- * Sets the child's visibility when it moves beyond or within the limits set by a call to
- * {@link PhysicsAnimationLayout#setMaxRenderedChildren}. This can be overridden to animate
- * this transition.
- */
- protected void setChildVisibility(View child, int index, int visibility) {
- child.setVisibility(visibility);
- }
-
- /**
* Returns a {@link PhysicsPropertyAnimator} instance for the given child view.
*/
protected PhysicsPropertyAnimator animationForChild(View child) {
@@ -170,6 +184,9 @@
child.setTag(R.id.physics_animator_tag, animator);
}
+ animator.clearAnimator();
+ animator.setAssociatedController(this);
+
return animator;
}
@@ -235,32 +252,17 @@
new HashMap<>();
/** The currently active animation controller. */
- private PhysicsAnimationController mController;
-
- /**
- * The maximum number of children to render and animate at a time. See
- * {@link #setMaxRenderedChildren}.
- */
- private int mMaxRenderedChildren = 5;
+ @Nullable protected PhysicsAnimationController mController;
public PhysicsAnimationLayout(Context context) {
super(context);
}
/**
- * The maximum number of children to render and animate at a time. Any child views added beyond
- * this limit will be set to {@link View#GONE}. If any animations attempt to run on the view,
- * the corresponding property will be set with no animation.
- */
- public void setMaxRenderedChildren(int max) {
- this.mMaxRenderedChildren = max;
- }
-
- /**
* Sets the animation controller and constructs or reconfigures the layout's physics animations
* to meet the controller's specifications.
*/
- public void setController(PhysicsAnimationController controller) {
+ public void setActiveController(PhysicsAnimationController controller) {
cancelAllAnimations();
mEndActionForProperty.clear();
@@ -312,42 +314,11 @@
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
- super.addView(child, index, params);
-
- // Set up animations for the new view, if the controller is set. If it isn't set, we'll be
- // setting up animations for all children when setController is called.
- if (mController != null) {
- for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
- setUpAnimationForChild(property, child, index);
- }
-
- mController.onChildAdded(child, index);
- }
-
- setChildrenVisibility();
+ addViewInternal(child, index, params, false /* isReorder */);
}
@Override
public void removeView(View view) {
- removeViewAndThen(view, /* callback */ null);
- }
-
- @Override
- public void removeViewAt(int index) {
- removeView(getChildAt(index));
- }
-
- /** Immediately moves the view from wherever it currently is, to the given index. */
- public void moveViewTo(View view, int index) {
- super.removeView(view);
- addView(view, index);
- }
-
- /**
- * Let the controller know that this view should be removed, and then call the callback once the
- * controller has finished any removal animations and the view has actually been removed.
- */
- public void removeViewAndThen(View view, Runnable callback) {
if (mController != null) {
final int index = indexOfChild(view);
@@ -355,8 +326,6 @@
super.removeView(view);
addTransientView(view, index);
- setChildrenVisibility();
-
// Tell the controller to animate this view out, and call the callback when it's
// finished.
mController.onChildRemoved(view, index, () -> {
@@ -364,19 +333,28 @@
// any are still running and then remove it.
cancelAnimationsOnView(view);
removeTransientView(view);
-
- if (callback != null) {
- callback.run();
- }
});
} else {
// Without a controller, nobody will animate this view out, so it gets an unceremonious
// departure.
super.removeView(view);
+ }
+ }
- if (callback != null) {
- callback.run();
- }
+ @Override
+ public void removeViewAt(int index) {
+ removeView(getChildAt(index));
+ }
+
+ /** Immediately re-orders the view to the given index. */
+ public void reorderView(View view, int index) {
+ final int oldIndex = indexOfChild(view);
+
+ super.removeView(view);
+ addViewInternal(view, index, view.getLayoutParams(), true /* isReorder */);
+
+ if (mController != null) {
+ mController.onChildReordered(view, oldIndex, index);
}
}
@@ -427,6 +405,10 @@
}
}
+ protected boolean isActiveController(PhysicsAnimationController controller) {
+ return mController == controller;
+ }
+
/** Whether the first child would be left of center if translated to the given x value. */
protected boolean isFirstChildXLeftOfCenter(float x) {
if (getChildCount() > 0) {
@@ -454,6 +436,26 @@
}
/**
+ * Adds a view to the layout. If this addition is not the result of a call to
+ * {@link #reorderView}, this will also notify the controller via
+ * {@link PhysicsAnimationController#onChildAdded} and set up animations for the view.
+ */
+ private void addViewInternal(
+ View child, int index, ViewGroup.LayoutParams params, boolean isReorder) {
+ super.addView(child, index, params);
+
+ // Set up animations for the new view, if the controller is set. If it isn't set, we'll be
+ // setting up animations for all children when setActiveController is called.
+ if (mController != null && !isReorder) {
+ for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
+ setUpAnimationForChild(property, child, index);
+ }
+
+ mController.onChildAdded(child, index);
+ }
+ }
+
+ /**
* Retrieves the animation of the given property from the view at the given index via the view
* tag system.
*/
@@ -481,33 +483,16 @@
SpringAnimation newAnim = new SpringAnimation(child, property);
newAnim.addUpdateListener((animation, value, velocity) -> {
final int indexOfChild = indexOfChild(child);
- final int nextAnimInChain =
- mController.getNextAnimationInChain(property, indexOfChild);
+ final int nextAnimInChain = mController.getNextAnimationInChain(property, indexOfChild);
if (nextAnimInChain == PhysicsAnimationController.NONE || indexOfChild < 0) {
return;
}
- final int animIndex = indexOfChild(child);
- final float offset =
- mController.getOffsetForChainedPropertyAnimation(property);
-
- // If this property's animations should be chained, then check to see if there is a
- // subsequent animation within the rendering limit, and if so, tell it to animate to
- // this animation's new value (plus the offset).
- if (nextAnimInChain < Math.min(getChildCount(), mMaxRenderedChildren)) {
- getAnimationAtIndex(property, animIndex + 1)
+ final float offset = mController.getOffsetForChainedPropertyAnimation(property);
+ if (nextAnimInChain < getChildCount()) {
+ getAnimationAtIndex(property, nextAnimInChain)
.animateToFinalPosition(value + offset);
- } else if (nextAnimInChain < getChildCount()) {
- // If the next child view is not rendered, update the property directly without
- // animating it, so that the view is still in the correct state if it later
- // becomes visible.
- for (int i = nextAnimInChain; i < getChildCount(); i++) {
- // 'value' here is the value of the last child within the rendering limit,
- // not the first child's value - so we want to subtract the last child's
- // index when calculating the offset.
- property.setValue(getChildAt(i), value + offset * (i - animIndex));
- }
}
});
@@ -516,22 +501,6 @@
child.setTag(getTagIdForProperty(property), newAnim);
}
- /** Hides children beyond the max rendering count. */
- private void setChildrenVisibility() {
- for (int i = 0; i < getChildCount(); i++) {
- final int targetVisibility = i < mMaxRenderedChildren ? View.VISIBLE : View.GONE;
- final View targetView = getChildAt(i);
-
- if (targetView.getVisibility() != targetVisibility) {
- if (mController != null) {
- mController.setChildVisibility(targetView, i, targetVisibility);
- } else {
- targetView.setVisibility(targetVisibility);
- }
- }
- }
- }
-
/** Return a stable ID to use as a tag key for the given property's animations. */
private int getTagIdForProperty(DynamicAnimation.ViewProperty property) {
if (property.equals(DynamicAnimation.TRANSLATION_X)) {
@@ -592,7 +561,7 @@
private View mView;
/** Start velocity to use for all property animations. */
- private float mDefaultStartVelocity = 0f;
+ private float mDefaultStartVelocity = -Float.MAX_VALUE;
/** Start delay to use when start is called. */
private long mStartDelay = 0;
@@ -625,6 +594,15 @@
*/
private Map<DynamicAnimation.ViewProperty, Float> mAnimatedProperties = new HashMap<>();
+ /**
+ * All of the initial property values that have been set. These values will be instantly set
+ * when {@link #start} is called, just before the animation begins.
+ */
+ private Map<DynamicAnimation.ViewProperty, Float> mInitialPropertyValues = new HashMap<>();
+
+ /** The animation controller that last retrieved this animator instance. */
+ private PhysicsAnimationController mAssociatedController;
+
protected PhysicsPropertyAnimator(View view) {
this.mView = view;
}
@@ -644,7 +622,7 @@
/** Set the view's alpha value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator alpha(float from, float to, Runnable... endActions) {
- mView.setAlpha(from);
+ mInitialPropertyValues.put(DynamicAnimation.ALPHA, from);
return alpha(to, endActions);
}
@@ -656,7 +634,7 @@
/** Set the view's translationX value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator translationX(
float from, float to, Runnable... endActions) {
- mView.setTranslationX(from);
+ mInitialPropertyValues.put(DynamicAnimation.TRANSLATION_X, from);
return translationX(to, endActions);
}
@@ -668,7 +646,7 @@
/** Set the view's translationY value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator translationY(
float from, float to, Runnable... endActions) {
- mView.setTranslationY(from);
+ mInitialPropertyValues.put(DynamicAnimation.TRANSLATION_Y, from);
return translationY(to, endActions);
}
@@ -690,7 +668,7 @@
/** Set the view's scaleX value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator scaleX(float from, float to, Runnable... endActions) {
- mView.setScaleX(from);
+ mInitialPropertyValues.put(DynamicAnimation.SCALE_X, from);
return scaleX(to, endActions);
}
@@ -701,7 +679,7 @@
/** Set the view's scaleY value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator scaleY(float from, float to, Runnable... endActions) {
- mView.setScaleY(from);
+ mInitialPropertyValues.put(DynamicAnimation.SCALE_Y, from);
return scaleY(to, endActions);
}
@@ -750,6 +728,13 @@
* animated property on every child (including chained animations) have ended.
*/
public void start(Runnable... after) {
+ if (!isActiveController(mAssociatedController)) {
+ Log.w(TAG, "Only the active animation controller is allowed to start animations. "
+ + "Use PhysicsAnimationLayout#setActiveController to set the active "
+ + "animation controller.");
+ return;
+ }
+
final Set<DynamicAnimation.ViewProperty> properties = getAnimatedProperties();
// If there are end actions, set an end listener on the layout for all the properties
@@ -791,6 +776,10 @@
// Actually start the animations.
for (DynamicAnimation.ViewProperty property : properties) {
+ if (mInitialPropertyValues.containsKey(property)) {
+ property.setValue(mView, mInitialPropertyValues.get(property));
+ }
+
final SpringForce defaultSpringForce = mController.getSpringForce(property, mView);
animateValueForChild(
property,
@@ -803,14 +792,7 @@
mEndActionsForProperty.get(property));
}
- // Clear out the animator.
- mAnimatedProperties.clear();
- mPositionStartVelocities.clear();
- mDefaultStartVelocity = 0;
- mStartDelay = 0;
- mStiffness = -1;
- mDampingRatio = -1;
- mEndActionsForProperty.clear();
+ clearAnimator();
}
/** Returns the set of properties that will animate once {@link #start} is called. */
@@ -847,20 +829,50 @@
});
}
- animation.getSpring().setStiffness(stiffness);
- animation.getSpring().setDampingRatio(dampingRatio);
+ final SpringForce animationSpring = animation.getSpring();
- if (startVel > 0) {
- animation.setStartVelocity(startVel);
+ if (animationSpring == null) {
+ return;
}
+ final Runnable configureAndStartAnimation = () -> {
+ animationSpring.setStiffness(stiffness);
+ animationSpring.setDampingRatio(dampingRatio);
+
+ if (startVel > -Float.MAX_VALUE) {
+ animation.setStartVelocity(startVel);
+ }
+
+ animationSpring.setFinalPosition(value);
+ animation.start();
+ };
+
if (startDelay > 0) {
- postDelayed(() -> animation.animateToFinalPosition(value), startDelay);
+ postDelayed(configureAndStartAnimation, startDelay);
} else {
- animation.animateToFinalPosition(value);
+ configureAndStartAnimation.run();
}
}
}
+
+ private void clearAnimator() {
+ mInitialPropertyValues.clear();
+ mAnimatedProperties.clear();
+ mPositionStartVelocities.clear();
+ mDefaultStartVelocity = -Float.MAX_VALUE;
+ mStartDelay = 0;
+ mStiffness = -1;
+ mDampingRatio = -1;
+ mEndActionsForProperty.clear();
+ }
+
+ /**
+ * Sets the controller that last retrieved this animator instance, so that we can prevent
+ * {@link #start} from actually starting animations if called by a non-active controller.
+ */
+ private void setAssociatedController(PhysicsAnimationController controller) {
+ mAssociatedController = controller;
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 7997dcb..356efc9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -154,21 +154,6 @@
/** Height of the status bar. */
private float mStatusBarHeight;
- @Override
- protected void setLayout(PhysicsAnimationLayout layout) {
- super.setLayout(layout);
-
- Resources res = layout.getResources();
- mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
- mIndividualBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
- mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
- mStackStartingVerticalOffset =
- res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- }
-
/**
* Instantly move the first bubble to the given point, and animate the rest of the stack behind
* it with the 'following' effect.
@@ -286,6 +271,8 @@
},
DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ // If we're flinging now, there's no more touch event to catch up to.
+ mFirstBubbleSpringingToTouch = false;
mIsMovingFromFlinging = true;
return destinationRelativeX;
}
@@ -656,19 +643,38 @@
if (mLayout.getChildCount() > 0) {
animationForChildAtIndex(0).translationX(mStackPosition.x).start();
+ } else {
+ // Set the start position back to the default since we're out of bubbles. New bubbles
+ // will then animate in from the start position.
+ mStackPosition = getDefaultStartPosition();
}
}
+ @Override
+ void onChildReordered(View child, int oldIndex, int newIndex) {}
+
+ @Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
+ Resources res = layout.getResources();
+ mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
+ mIndividualBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
+ mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
+ mStackStartingVerticalOffset =
+ res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
+ mStatusBarHeight =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ }
+
/** Moves the stack, without any animation, to the starting position. */
private void moveStackToStartPosition() {
// Post to ensure that the layout's width and height have been calculated.
mLayout.setVisibility(View.INVISIBLE);
mLayout.post(() -> {
+ setStackPosition(mRestingStackPosition == null
+ ? getDefaultStartPosition()
+ : mRestingStackPosition);
mStackMovedToStartPosition = true;
- setStackPosition(
- mRestingStackPosition == null
- ? getDefaultStartPosition()
- : mRestingStackPosition);
mLayout.setVisibility(View.VISIBLE);
// Animate in the top bubble now that we're visible.
@@ -707,15 +713,20 @@
Log.d(TAG, String.format("Setting position to (%f, %f).", pos.x, pos.y));
mStackPosition.set(pos.x, pos.y);
- mLayout.cancelAllAnimations();
- cancelStackPositionAnimations();
+ // If we're not the active controller, we don't want to physically move the bubble views.
+ if (isActiveController()) {
+ mLayout.cancelAllAnimations();
+ cancelStackPositionAnimations();
- // Since we're not using the chained animations, apply the offsets manually.
- final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
- final float yOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_Y);
- for (int i = 0; i < mLayout.getChildCount(); i++) {
- mLayout.getChildAt(i).setTranslationX(pos.x + (i * xOffset));
- mLayout.getChildAt(i).setTranslationY(pos.y + (i * yOffset));
+ // Since we're not using the chained animations, apply the offsets manually.
+ final float xOffset = getOffsetForChainedPropertyAnimation(
+ DynamicAnimation.TRANSLATION_X);
+ final float yOffset = getOffsetForChainedPropertyAnimation(
+ DynamicAnimation.TRANSLATION_Y);
+ for (int i = 0; i < mLayout.getChildCount(); i++) {
+ mLayout.getChildAt(i).setTranslationX(pos.x + (i * xOffset));
+ mLayout.getChildAt(i).setTranslationY(pos.y + (i * yOffset));
+ }
}
}
@@ -732,6 +743,10 @@
/** Animates in the given bubble. */
private void animateInBubble(View child) {
+ if (!isActiveController()) {
+ return;
+ }
+
child.setTranslationY(mStackPosition.y);
float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index 43dd4ee..10b631d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -62,8 +62,8 @@
@Before
public void setUp() throws Exception {
super.setUp();
- addOneMoreThanRenderLimitBubbles();
- mLayout.setController(mExpandedController);
+ addOneMoreThanBubbleLimitBubbles();
+ mLayout.setActiveController(mExpandedController);
Resources res = mLayout.getResources();
mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
@@ -75,14 +75,14 @@
@Test
public void testExpansionAndCollapse() throws InterruptedException {
Runnable afterExpand = Mockito.mock(Runnable.class);
- mExpandedController.expandFromStack(mExpansionPoint, afterExpand);
+ mExpandedController.expandFromStack(afterExpand);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testBubblesInCorrectExpandedPositions();
verify(afterExpand).run();
Runnable afterCollapse = Mockito.mock(Runnable.class);
- mExpandedController.collapseBackToStack(afterCollapse);
+ mExpandedController.collapseBackToStack(mExpansionPoint, afterCollapse);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testStackedAtPosition(mExpansionPoint.x, mExpansionPoint.y, -1);
@@ -140,8 +140,6 @@
assertEquals(500f, draggedBubble.getTranslationX(), 1f);
assertEquals(500f, draggedBubble.getTranslationY(), 1f);
- // Snap bubble back and make sure it returned correctly.
- mExpandedController.prepareForDismissalWithVelocity(draggedBubble);
mLayout.removeView(draggedBubble);
waitForLayoutMessageQueue();
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
@@ -171,7 +169,7 @@
// Dismiss the now-magneted bubble, verify that the callback was called.
final Runnable afterDismiss = Mockito.mock(Runnable.class);
- mExpandedController.dismissDraggedOutBubble(afterDismiss);
+ mExpandedController.dismissDraggedOutBubble(draggedOutView, afterDismiss);
waitForPropertyAnimations(DynamicAnimation.ALPHA);
verify(after).run();
@@ -226,7 +224,7 @@
/** Expand the stack and wait for animations to finish. */
private void expand() throws InterruptedException {
- mExpandedController.expandFromStack(mExpansionPoint, Mockito.mock(Runnable.class));
+ mExpandedController.expandFromStack(Mockito.mock(Runnable.class));
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
}
@@ -238,26 +236,19 @@
assertEquals(x + i * offsetMultiplier * mStackOffset,
mLayout.getChildAt(i).getTranslationX(), 2f);
assertEquals(y, mLayout.getChildAt(i).getTranslationY(), 2f);
-
- if (i < mMaxRenderedBubbles) {
- assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
- }
+ assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
}
}
/** Check that children are in the correct positions for being expanded. */
private void testBubblesInCorrectExpandedPositions() {
// Check all the visible bubbles to see if they're in the right place.
- for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) {
+ for (int i = 0; i < mLayout.getChildCount(); i++) {
assertEquals(getBubbleLeft(i),
mLayout.getChildAt(i).getTranslationX(),
2f);
assertEquals(mExpandedController.getExpandedY(),
mLayout.getChildAt(i).getTranslationY(), 2f);
-
- if (i < mMaxRenderedBubbles) {
- assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
- }
}
}
@@ -275,9 +266,6 @@
return 0;
}
int bubbleCount = mLayout.getChildCount();
- if (bubbleCount > mMaxRenderedBubbles) {
- bubbleCount = mMaxRenderedBubbles;
- }
final float totalBubbleWidth = bubbleCount * mBubbleSize;
final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
final float rowWidth = totalGapWidth + totalBubbleWidth;
@@ -297,10 +285,10 @@
final float rowMargins = (mExpandedViewPadding + launcherGridDiff) * 2;
final float maxRowWidth = mDisplayWidth - rowMargins;
- final float totalBubbleWidth = mMaxRenderedBubbles * mBubbleSize;
+ final float totalBubbleWidth = mMaxBubbles * mBubbleSize;
final float totalGapWidth = maxRowWidth - totalBubbleWidth;
- final int gapCount = mMaxRenderedBubbles - 1;
+ final int gapCount = mMaxBubbles - 1;
final float gapWidth = totalGapWidth / gapCount;
return gapWidth;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java
index eef6ddc..f8b32c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java
@@ -23,7 +23,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -77,21 +76,9 @@
}
@Test
- public void testRenderVisibility() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
-
- // The last child should be GONE, the rest VISIBLE.
- for (int i = 0; i < mMaxRenderedBubbles + 1; i++) {
- assertEquals(i == mMaxRenderedBubbles ? View.GONE : View.VISIBLE,
- mLayout.getChildAt(i).getVisibility());
- }
- }
-
- @Test
public void testHierarchyChanges() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
// Make sure the controller was notified of all the views we added.
for (View mView : mViews) {
@@ -115,8 +102,8 @@
@Test
public void testUpdateValueNotChained() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
// Don't chain any values.
mTestableController.setChainedProperties(Sets.newHashSet());
@@ -146,8 +133,8 @@
@Test
public void testSetEndActions() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
mTestableController.setChainedProperties(Sets.newHashSet());
final CountDownLatch xLatch = new CountDownLatch(1);
@@ -189,8 +176,8 @@
@Test
public void testRemoveEndListeners() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
mTestableController.setChainedProperties(Sets.newHashSet());
final CountDownLatch xLatch = new CountDownLatch(1);
@@ -229,8 +216,8 @@
public void testSetController() throws InterruptedException {
// Add the bubbles, then set the controller, to make sure that a controller added to an
// already-initialized view works correctly.
- addOneMoreThanRenderLimitBubbles();
- mLayout.setController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
+ mLayout.setActiveController(mTestableController);
testChainedTranslationAnimations();
TestableAnimationController secondController =
@@ -243,7 +230,7 @@
DynamicAnimation.SCALE_X, 10f);
secondController.setRemoveImmediately(true);
- mLayout.setController(secondController);
+ mLayout.setActiveController(secondController);
mTestableController.animationForChildAtIndex(0)
.scaleX(1.5f)
.start();
@@ -266,7 +253,7 @@
Mockito.verify(secondController, Mockito.atLeastOnce())
.getOffsetForChainedPropertyAnimation(eq(DynamicAnimation.SCALE_X));
- mLayout.setController(mTestableController);
+ mLayout.setActiveController(mTestableController);
mTestableController.animationForChildAtIndex(0)
.translationX(100f)
.start();
@@ -283,8 +270,8 @@
@Test
public void testArePropertiesAnimating() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
assertFalse(mLayout.arePropertiesAnimating(
DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y));
@@ -307,8 +294,8 @@
@Test
public void testCancelAllAnimations() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
mTestableController.animationForChildAtIndex(0)
.position(1000, 1000)
@@ -321,29 +308,10 @@
assertTrue(mViews.get(0).getTranslationY() < 1000);
}
- @Test
- public void testSetChildVisibility() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
-
- // The last view should have been set to GONE by the controller, since we added one more
- // than the limit and it got pushed off. None of the first children should have been set
- // VISIBLE, since they would have been animated in by onChildAdded.
- Mockito.verify(mTestableController).setChildVisibility(
- mViews.get(mViews.size() - 1), 5, View.GONE);
- Mockito.verify(mTestableController, never()).setChildVisibility(
- any(View.class), anyInt(), eq(View.VISIBLE));
-
- // Remove the first view, which should cause the last view to become visible again.
- mLayout.removeView(mViews.get(0));
- Mockito.verify(mTestableController).setChildVisibility(
- mViews.get(mViews.size() - 1), 4, View.VISIBLE);
- }
-
/** Standard test of chained translation animations. */
private void testChainedTranslationAnimations() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
assertEquals(0, mLayout.getChildAt(0).getTranslationX(), .1f);
assertEquals(0, mLayout.getChildAt(1).getTranslationX(), .1f);
@@ -354,11 +322,7 @@
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X);
- // Since we enabled chaining, animating the first view to 100 should animate the second to
- // 115 (since we set the offset to 15) and the third to 130, etc. Despite the sixth bubble
- // not being visible, or animated, make sure that it has the appropriate chained
- // translation.
- for (int i = 0; i < mMaxRenderedBubbles + 1; i++) {
+ for (int i = 0; i < mLayout.getChildCount(); i++) {
assertEquals(
100 + i * TEST_TRANSLATION_X_OFFSET,
mLayout.getChildAt(i).getTranslationX(), .1f);
@@ -383,8 +347,8 @@
@Test
public void testPhysicsAnimator() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
Runnable afterAll = Mockito.mock(Runnable.class);
Runnable after = Mockito.spy(new Runnable() {
@@ -430,9 +394,9 @@
// Don't chain since we're going to invoke each animation independently.
mTestableController.setChainedProperties(new HashSet<>());
- mLayout.setController(mTestableController);
+ mLayout.setActiveController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ addOneMoreThanBubbleLimitBubbles();
Runnable allEnd = Mockito.mock(Runnable.class);
@@ -452,7 +416,7 @@
@Test
public void testAnimationsForChildrenFromIndex_noChildren() {
- mLayout.setController(mTestableController);
+ mLayout.setActiveController(mTestableController);
final Runnable after = Mockito.mock(Runnable.class);
mTestableController
@@ -523,8 +487,9 @@
}
@Override
- protected void setChildVisibility(View child, int index, int visibility) {
- super.setChildVisibility(child, index, visibility);
- }
+ void onChildReordered(View child, int oldIndex, int newIndex) {}
+
+ @Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
index c6acef5d..2ae759f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
@@ -56,7 +56,6 @@
Handler mMainThreadHandler;
- int mMaxRenderedBubbles;
int mSystemWindowInsetSize = 50;
int mCutoutInsetSize = 100;
@@ -69,6 +68,8 @@
@Mock
private DisplayCutout mCutout;
+ protected int mMaxBubbles;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -79,7 +80,7 @@
mLayout.setTop(0);
mLayout.setBottom(mHeight);
- mMaxRenderedBubbles =
+ mMaxBubbles =
getContext().getResources().getInteger(R.integer.bubbles_max_rendered);
mMainThreadHandler = new Handler(Looper.getMainLooper());
@@ -96,8 +97,8 @@
}
/** Add one extra bubble over the limit, so we can make sure it's gone/chains appropriately. */
- void addOneMoreThanRenderLimitBubbles() throws InterruptedException {
- for (int i = 0; i < mMaxRenderedBubbles + 1; i++) {
+ void addOneMoreThanBubbleLimitBubbles() throws InterruptedException {
+ for (int i = 0; i < mMaxBubbles + 1; i++) {
final View newView = new FrameLayout(mContext);
mLayout.addView(newView, 0);
mViews.add(0, newView);
@@ -138,6 +139,13 @@
}
@Override
+ protected boolean isActiveController(PhysicsAnimationController controller) {
+ // Return true since otherwise all test controllers will be seen as inactive since they
+ // are wrapped by MainThreadAnimationControllerWrapper.
+ return true;
+ }
+
+ @Override
public boolean post(Runnable action) {
return mMainThreadHandler.post(action);
}
@@ -148,9 +156,9 @@
}
@Override
- public void setController(PhysicsAnimationController controller) {
+ public void setActiveController(PhysicsAnimationController controller) {
runOnMainThreadAndBlock(
- () -> super.setController(
+ () -> super.setActiveController(
new MainThreadAnimationControllerWrapper(controller)));
}
@@ -267,8 +275,15 @@
}
@Override
- protected void setChildVisibility(View child, int index, int visibility) {
- mWrappedController.setChildVisibility(child, index, visibility);
+ void onChildReordered(View child, int oldIndex, int newIndex) {
+ runOnMainThreadAndBlock(
+ () -> mWrappedController.onChildReordered(child, oldIndex, newIndex));
+ }
+
+ @Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
+ runOnMainThreadAndBlock(
+ () -> mWrappedController.onActiveControllerForLayout(layout));
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 9218a8b..31a7d5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -54,8 +54,8 @@
@Before
public void setUp() throws Exception {
super.setUp();
- mLayout.setController(mStackController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mStackController);
+ addOneMoreThanBubbleLimitBubbles();
mStackOffset = mLayout.getResources().getDimensionPixelSize(R.dimen.bubble_stack_offset);
}