Merge "Log.wtf when float properties in ViewState are set to NaN." into tm-qpr-dev
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index d67f94f..f961984 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -189,22 +189,22 @@
viewState.copyFrom(lastViewState);
viewState.height = getIntrinsicHeight();
- viewState.zTranslation = ambientState.getBaseZHeight();
+ viewState.setZTranslation(ambientState.getBaseZHeight());
viewState.clipTopAmount = 0;
if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) {
float expansion = ambientState.getExpansionFraction();
if (ambientState.isBouncerInTransit()) {
- viewState.alpha = aboutToShowBouncerProgress(expansion);
+ viewState.setAlpha(aboutToShowBouncerProgress(expansion));
} else {
- viewState.alpha = ShadeInterpolation.getContentAlpha(expansion);
+ viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
}
} else {
- viewState.alpha = 1f - ambientState.getHideAmount();
+ viewState.setAlpha(1f - ambientState.getHideAmount());
}
viewState.belowSpeedBump = mHostLayoutController.getSpeedBumpIndex() == 0;
viewState.hideSensitive = false;
- viewState.xTranslation = getTranslationX();
+ viewState.setXTranslation(getTranslationX());
viewState.hasItemsInStableShelf = lastViewState.inShelf;
viewState.firstViewInShelf = algorithmState.firstViewInShelf;
if (mNotGoneIndex != -1) {
@@ -230,7 +230,7 @@
}
final float stackEnd = ambientState.getStackY() + ambientState.getStackHeight();
- viewState.yTranslation = stackEnd - viewState.height;
+ viewState.setYTranslation(stackEnd - viewState.height);
} else {
viewState.hidden = true;
viewState.location = ExpandableViewState.LOCATION_GONE;
@@ -794,7 +794,7 @@
if (iconState == null) {
return;
}
- iconState.alpha = ICON_ALPHA_INTERPOLATOR.getInterpolation(transitionAmount);
+ iconState.setAlpha(ICON_ALPHA_INTERPOLATOR.getInterpolation(transitionAmount));
boolean isAppearing = row.isDrawingAppearAnimation() && !row.isInShelf();
iconState.hidden = isAppearing
|| (view instanceof ExpandableNotificationRow
@@ -809,12 +809,12 @@
// Fade in icons at shelf start
// This is important for conversation icons, which are badged and need x reset
- iconState.xTranslation = mShelfIcons.getActualPaddingStart();
+ iconState.setXTranslation(mShelfIcons.getActualPaddingStart());
final boolean stayingInShelf = row.isInShelf() && !row.isTransformingIntoShelf();
if (stayingInShelf) {
iconState.iconAppearAmount = 1.0f;
- iconState.alpha = 1.0f;
+ iconState.setAlpha(1.0f);
iconState.hidden = false;
}
int backgroundColor = getBackgroundColorWithoutTint();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 07ed013..087dc71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -3376,7 +3376,7 @@
private void handleFixedTranslationZ(ExpandableNotificationRow row) {
if (row.hasExpandingChild()) {
- zTranslation = row.getTranslationZ();
+ setZTranslation(row.getTranslationZ());
clipTopAmount = row.getClipTopAmount();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 1e09b8a..38f0c55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -621,12 +621,12 @@
// initialize with the default values of the view
mViewState.height = getIntrinsicHeight();
mViewState.gone = getVisibility() == View.GONE;
- mViewState.alpha = 1f;
+ mViewState.setAlpha(1f);
mViewState.notGoneIndex = -1;
- mViewState.xTranslation = getTranslationX();
+ mViewState.setXTranslation(getTranslationX());
mViewState.hidden = false;
- mViewState.scaleX = getScaleX();
- mViewState.scaleY = getScaleY();
+ mViewState.setScaleX(getScaleX());
+ mViewState.setScaleY(getScaleY());
mViewState.inShelf = false;
mViewState.headsUpIsVisible = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index d77e03f..7b23a56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -583,24 +583,26 @@
ExpandableViewState childState = child.getViewState();
int intrinsicHeight = child.getIntrinsicHeight();
childState.height = intrinsicHeight;
- childState.yTranslation = yPosition + launchTransitionCompensation;
+ childState.setYTranslation(yPosition + launchTransitionCompensation);
childState.hidden = false;
// When the group is expanded, the children cast the shadows rather than the parent
// so use the parent's elevation here.
- childState.zTranslation =
- (childrenExpandedAndNotAnimating && mEnableShadowOnChildNotifications)
- ? parentState.zTranslation
- : 0;
+ if (childrenExpandedAndNotAnimating && mEnableShadowOnChildNotifications) {
+ childState.setZTranslation(parentState.getZTranslation());
+ } else {
+ childState.setZTranslation(0);
+ }
childState.dimmed = parentState.dimmed;
childState.hideSensitive = parentState.hideSensitive;
childState.belowSpeedBump = parentState.belowSpeedBump;
childState.clipTopAmount = 0;
- childState.alpha = 0;
+ childState.setAlpha(0);
if (i < firstOverflowIndex) {
- childState.alpha = showingAsLowPriority() ? expandFactor : 1.0f;
+ childState.setAlpha(showingAsLowPriority() ? expandFactor : 1.0f);
} else if (expandFactor == 1.0f && i <= lastVisibleIndex) {
- childState.alpha = (mActualHeight - childState.yTranslation) / childState.height;
- childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha));
+ childState.setAlpha(
+ (mActualHeight - childState.getYTranslation()) / childState.height);
+ childState.setAlpha(Math.max(0.0f, Math.min(1.0f, childState.getAlpha())));
}
childState.location = parentState.location;
childState.inShelf = parentState.inShelf;
@@ -621,13 +623,16 @@
if (mirrorView.getVisibility() == GONE) {
mirrorView = alignView;
}
- mGroupOverFlowState.alpha = mirrorView.getAlpha();
- mGroupOverFlowState.yTranslation += NotificationUtils.getRelativeYOffset(
+ mGroupOverFlowState.setAlpha(mirrorView.getAlpha());
+ float yTranslation = mGroupOverFlowState.getYTranslation()
+ + NotificationUtils.getRelativeYOffset(
mirrorView, overflowView);
+ mGroupOverFlowState.setYTranslation(yTranslation);
}
} else {
- mGroupOverFlowState.yTranslation += mNotificationHeaderMargin;
- mGroupOverFlowState.alpha = 0.0f;
+ mGroupOverFlowState.setYTranslation(
+ mGroupOverFlowState.getYTranslation() + mNotificationHeaderMargin);
+ mGroupOverFlowState.setAlpha(0.0f);
}
}
if (mNotificationHeader != null) {
@@ -635,11 +640,11 @@
mHeaderViewState = new ViewState();
}
mHeaderViewState.initFrom(mNotificationHeader);
- mHeaderViewState.zTranslation = childrenExpandedAndNotAnimating
- ? parentState.zTranslation
- : 0;
- mHeaderViewState.yTranslation = mCurrentHeaderTranslation;
- mHeaderViewState.alpha = mHeaderVisibleAmount;
+ mHeaderViewState.setZTranslation(childrenExpandedAndNotAnimating
+ ? parentState.getZTranslation()
+ : 0);
+ mHeaderViewState.setYTranslation(mCurrentHeaderTranslation);
+ mHeaderViewState.setAlpha(mHeaderVisibleAmount);
// The hiding is done automatically by the alpha, otherwise we'll pick it up again
// in the next frame with the initFrom call above and have an invisible header
mHeaderViewState.hidden = false;
@@ -711,14 +716,14 @@
// layout the divider
View divider = mDividers.get(i);
tmpState.initFrom(divider);
- tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
- float alpha = mChildrenExpanded && viewState.alpha != 0 ? mDividerAlpha : 0;
- if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
+ tmpState.setYTranslation(viewState.getYTranslation() - mDividerHeight);
+ float alpha = mChildrenExpanded && viewState.getAlpha() != 0 ? mDividerAlpha : 0;
+ if (mUserLocked && !showingAsLowPriority() && viewState.getAlpha() != 0) {
alpha = NotificationUtils.interpolate(0, mDividerAlpha,
- Math.min(viewState.alpha, expandFraction));
+ Math.min(viewState.getAlpha(), expandFraction));
}
tmpState.hidden = !dividersVisible;
- tmpState.alpha = alpha;
+ tmpState.setAlpha(alpha);
tmpState.applyToView(divider);
// There is no fake shadow to be drawn on the children
child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
@@ -790,24 +795,24 @@
// layout the divider
View divider = mDividers.get(i);
tmpState.initFrom(divider);
- tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
- float alpha = mChildrenExpanded && viewState.alpha != 0 ? mDividerAlpha : 0;
- if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
+ tmpState.setYTranslation(viewState.getYTranslation() - mDividerHeight);
+ float alpha = mChildrenExpanded && viewState.getAlpha() != 0 ? mDividerAlpha : 0;
+ if (mUserLocked && !showingAsLowPriority() && viewState.getAlpha() != 0) {
alpha = NotificationUtils.interpolate(0, mDividerAlpha,
- Math.min(viewState.alpha, expandFraction));
+ Math.min(viewState.getAlpha(), expandFraction));
}
tmpState.hidden = !dividersVisible;
- tmpState.alpha = alpha;
+ tmpState.setAlpha(alpha);
tmpState.animateTo(divider, properties);
// There is no fake shadow to be drawn on the children
child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
}
if (mOverflowNumber != null) {
if (mNeverAppliedGroupState) {
- float alpha = mGroupOverFlowState.alpha;
- mGroupOverFlowState.alpha = 0;
+ float alpha = mGroupOverFlowState.getAlpha();
+ mGroupOverFlowState.setAlpha(0);
mGroupOverFlowState.applyToView(mOverflowNumber);
- mGroupOverFlowState.alpha = alpha;
+ mGroupOverFlowState.setAlpha(alpha);
mNeverAppliedGroupState = false;
}
mGroupOverFlowState.animateTo(mOverflowNumber, properties);
@@ -949,7 +954,7 @@
child.setAlpha(start);
ViewState viewState = new ViewState();
viewState.initFrom(child);
- viewState.alpha = target;
+ viewState.setAlpha(target);
ALPHA_FADE_IN.setDelay(i * 50);
viewState.animateTo(child, ALPHA_FADE_IN);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 6821b14..836cacc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -3188,7 +3188,7 @@
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private boolean shouldHunAppearFromBottom(ExpandableViewState viewState) {
- return viewState.yTranslation + viewState.height
+ return viewState.getYTranslation() + viewState.height
>= mAmbientState.getMaxHeadsUpTranslation();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 32591ce..8d28f75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -134,23 +134,23 @@
if (isHunGoingToShade) {
// Keep 100% opacity for heads up notification going to shade.
- viewState.alpha = 1f;
+ viewState.setAlpha(1f);
} else if (ambientState.isOnKeyguard()) {
// Adjust alpha for wakeup to lockscreen.
- viewState.alpha = 1f - ambientState.getHideAmount();
+ viewState.setAlpha(1f - ambientState.getHideAmount());
} else if (ambientState.isExpansionChanging()) {
// Adjust alpha for shade open & close.
float expansion = ambientState.getExpansionFraction();
- viewState.alpha = ambientState.isBouncerInTransit()
+ viewState.setAlpha(ambientState.isBouncerInTransit()
? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
- : ShadeInterpolation.getContentAlpha(expansion);
+ : ShadeInterpolation.getContentAlpha(expansion));
}
// For EmptyShadeView if on keyguard, we need to control the alpha to create
// a nice transition when the user is dragging down the notification panel.
if (view instanceof EmptyShadeView && ambientState.isOnKeyguard()) {
final float fractionToShade = ambientState.getFractionToShade();
- viewState.alpha = ShadeInterpolation.getContentAlpha(fractionToShade);
+ viewState.setAlpha(ShadeInterpolation.getContentAlpha(fractionToShade));
}
NotificationShelf shelf = ambientState.getShelf();
@@ -166,10 +166,10 @@
continue;
}
- final float shelfTop = shelfState.yTranslation;
- final float viewTop = viewState.yTranslation;
+ final float shelfTop = shelfState.getYTranslation();
+ final float viewTop = viewState.getYTranslation();
if (viewTop >= shelfTop) {
- viewState.alpha = 0;
+ viewState.setAlpha(0);
}
}
}
@@ -277,7 +277,7 @@
if (!child.mustStayOnScreen() || state.headsUpIsVisible) {
clipStart = Math.max(drawStart, clipStart);
}
- float newYTranslation = state.yTranslation;
+ float newYTranslation = state.getYTranslation();
float newHeight = state.height;
float newNotificationEnd = newYTranslation + newHeight;
boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned();
@@ -322,7 +322,8 @@
childViewState.hideSensitive = hideSensitive;
boolean isActivatedChild = activatedChild == child;
if (dimmed && isActivatedChild) {
- childViewState.zTranslation += 2.0f * ambientState.getZDistanceBetweenElements();
+ childViewState.setZTranslation(childViewState.getZTranslation()
+ + 2.0f * ambientState.getZDistanceBetweenElements());
}
}
}
@@ -527,12 +528,12 @@
// Must set viewState.yTranslation _before_ use.
// Incoming views have yTranslation=0 by default.
- viewState.yTranslation = algorithmState.mCurrentYPosition;
+ viewState.setYTranslation(algorithmState.mCurrentYPosition);
+ float viewEnd = viewState.getYTranslation() + viewState.height + ambientState.getStackY();
maybeUpdateHeadsUpIsVisible(viewState, ambientState.isShadeExpanded(),
- view.mustStayOnScreen(), /* topVisible */ viewState.yTranslation >= 0,
- /* viewEnd */ viewState.yTranslation + viewState.height + ambientState.getStackY(),
- /* hunMax */ ambientState.getMaxHeadsUpTranslation()
+ view.mustStayOnScreen(), /* topVisible */ viewState.getYTranslation() >= 0,
+ viewEnd, /* hunMax */ ambientState.getMaxHeadsUpTranslation()
);
if (view instanceof FooterView) {
final boolean shadeClosed = !ambientState.isShadeExpanded();
@@ -552,7 +553,7 @@
if (view instanceof EmptyShadeView) {
float fullHeight = ambientState.getLayoutMaxHeight() + mMarginBottom
- ambientState.getStackY();
- viewState.yTranslation = (fullHeight - getMaxAllowedChildHeight(view)) / 2f;
+ viewState.setYTranslation((fullHeight - getMaxAllowedChildHeight(view)) / 2f);
} else if (view != ambientState.getTrackedHeadsUpRow()) {
if (ambientState.isExpansionChanging()) {
// We later update shelf state, then hide views below the shelf.
@@ -591,13 +592,13 @@
+ mPaddingBetweenElements;
setLocation(view.getViewState(), algorithmState.mCurrentYPosition, i);
- viewState.yTranslation += ambientState.getStackY();
+ viewState.setYTranslation(viewState.getYTranslation() + ambientState.getStackY());
}
@VisibleForTesting
void updateViewWithShelf(ExpandableView view, ExpandableViewState viewState, float shelfStart) {
- viewState.yTranslation = Math.min(viewState.yTranslation, shelfStart);
- if (viewState.yTranslation >= shelfStart) {
+ viewState.setYTranslation(Math.min(viewState.getYTranslation(), shelfStart));
+ if (viewState.getYTranslation() >= shelfStart) {
viewState.hidden = !view.isExpandAnimationRunning()
&& !view.hasExpandingChild();
viewState.inShelf = true;
@@ -690,9 +691,9 @@
if (trackedHeadsUpRow != null) {
ExpandableViewState childState = trackedHeadsUpRow.getViewState();
if (childState != null) {
- float endPosition = childState.yTranslation - ambientState.getStackTranslation();
- childState.yTranslation = MathUtils.lerp(
- headsUpTranslation, endPosition, ambientState.getAppearFraction());
+ float endPos = childState.getYTranslation() - ambientState.getStackTranslation();
+ childState.setYTranslation(MathUtils.lerp(
+ headsUpTranslation, endPos, ambientState.getAppearFraction()));
}
}
@@ -712,7 +713,7 @@
childState.location = ExpandableViewState.LOCATION_FIRST_HUN;
}
boolean isTopEntry = topHeadsUpEntry == row;
- float unmodifiedEndLocation = childState.yTranslation + childState.height;
+ float unmodifiedEndLocation = childState.getYTranslation() + childState.height;
if (mIsExpanded) {
if (row.mustStayOnScreen() && !childState.headsUpIsVisible
&& !row.showingPulsing()) {
@@ -727,13 +728,14 @@
}
}
if (row.isPinned()) {
- childState.yTranslation = Math.max(childState.yTranslation, headsUpTranslation);
+ childState.setYTranslation(
+ Math.max(childState.getYTranslation(), headsUpTranslation));
childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
childState.hidden = false;
ExpandableViewState topState =
topHeadsUpEntry == null ? null : topHeadsUpEntry.getViewState();
if (topState != null && !isTopEntry && (!mIsExpanded
- || unmodifiedEndLocation > topState.yTranslation + topState.height)) {
+ || unmodifiedEndLocation > topState.getYTranslation() + topState.height)) {
// Ensure that a headsUp doesn't vertically extend further than the heads-up at
// the top most z-position
childState.height = row.getIntrinsicHeight();
@@ -745,11 +747,12 @@
// heads up show full of row's content and any scroll y indicate that the
// translationY need to move up the HUN.
if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) {
- childState.yTranslation -= ambientState.getScrollY();
+ childState.setYTranslation(
+ childState.getYTranslation() - ambientState.getScrollY());
}
}
if (row.isHeadsUpAnimatingAway()) {
- childState.yTranslation = Math.max(childState.yTranslation, mHeadsUpInset);
+ childState.setYTranslation(Math.max(childState.getYTranslation(), mHeadsUpInset));
childState.hidden = false;
}
}
@@ -765,13 +768,13 @@
ExpandableViewState viewState) {
final float newTranslation = Math.max(quickQsOffsetHeight + stackTranslation,
- viewState.yTranslation);
+ viewState.getYTranslation());
// Transition from collapsed pinned state to fully expanded state
// when the pinned HUN approaches its actual location (when scrolling back to top).
- final float distToRealY = newTranslation - viewState.yTranslation;
+ final float distToRealY = newTranslation - viewState.getYTranslation();
viewState.height = (int) Math.max(viewState.height - distToRealY, collapsedHeight);
- viewState.yTranslation = newTranslation;
+ viewState.setYTranslation(newTranslation);
}
// Pin HUN to bottom of expanded QS
@@ -784,10 +787,10 @@
maxHeadsUpTranslation = Math.min(maxHeadsUpTranslation, maxShelfPosition);
final float bottomPosition = maxHeadsUpTranslation - row.getCollapsedHeight();
- final float newTranslation = Math.min(childState.yTranslation, bottomPosition);
+ final float newTranslation = Math.min(childState.getYTranslation(), bottomPosition);
childState.height = (int) Math.min(childState.height, maxHeadsUpTranslation
- newTranslation);
- childState.yTranslation = newTranslation;
+ childState.setYTranslation(newTranslation);
// Animate pinned HUN bottom corners to and from original roundness.
final float originalCornerRadius =
@@ -859,17 +862,17 @@
float baseZ = ambientState.getBaseZHeight();
if (child.mustStayOnScreen() && !childViewState.headsUpIsVisible
&& !ambientState.isDozingAndNotPulsing(child)
- && childViewState.yTranslation < ambientState.getTopPadding()
+ && childViewState.getYTranslation() < ambientState.getTopPadding()
+ ambientState.getStackTranslation()) {
if (childrenOnTop != 0.0f) {
childrenOnTop++;
} else {
float overlap = ambientState.getTopPadding()
- + ambientState.getStackTranslation() - childViewState.yTranslation;
+ + ambientState.getStackTranslation() - childViewState.getYTranslation();
childrenOnTop += Math.min(1.0f, overlap / childViewState.height);
}
- childViewState.zTranslation = baseZ
- + childrenOnTop * zDistanceBetweenElements;
+ childViewState.setZTranslation(baseZ
+ + childrenOnTop * zDistanceBetweenElements);
} else if (shouldElevateHun) {
// In case this is a new view that has never been measured before, we don't want to
// elevate if we are currently expanded more then the notification
@@ -878,28 +881,28 @@
float shelfStart = ambientState.getInnerHeight()
- shelfHeight + ambientState.getTopPadding()
+ ambientState.getStackTranslation();
- float notificationEnd = childViewState.yTranslation + child.getIntrinsicHeight()
+ float notificationEnd = childViewState.getYTranslation() + child.getIntrinsicHeight()
+ mPaddingBetweenElements;
if (shelfStart > notificationEnd) {
- childViewState.zTranslation = baseZ;
+ childViewState.setZTranslation(baseZ);
} else {
float factor = (notificationEnd - shelfStart) / shelfHeight;
if (Float.isNaN(factor)) { // Avoid problems when the above is 0/0.
factor = 1.0f;
}
factor = Math.min(factor, 1.0f);
- childViewState.zTranslation = baseZ + factor * zDistanceBetweenElements;
+ childViewState.setZTranslation(baseZ + factor * zDistanceBetweenElements);
}
} else {
- childViewState.zTranslation = baseZ;
+ childViewState.setZTranslation(baseZ);
}
// We need to scrim the notification more from its surrounding content when we are pinned,
// and we therefore elevate it higher.
// We can use the headerVisibleAmount for this, since the value nicely goes from 0 to 1 when
// expanding after which we have a normal elevation again.
- childViewState.zTranslation += (1.0f - child.getHeaderVisibleAmount())
- * mPinnedZTranslationExtra;
+ childViewState.setZTranslation(childViewState.getZTranslation()
+ + (1.0f - child.getHeaderVisibleAmount()) * mPinnedZTranslationExtra);
return childrenOnTop;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 174bf4c..ee72943 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -169,9 +169,9 @@
adaptDurationWhenGoingToFullShade(child, viewState, wasAdded, animationStaggerCount);
mAnimationProperties.delay = 0;
if (wasAdded || mAnimationFilter.hasDelays
- && (viewState.yTranslation != child.getTranslationY()
- || viewState.zTranslation != child.getTranslationZ()
- || viewState.alpha != child.getAlpha()
+ && (viewState.getYTranslation() != child.getTranslationY()
+ || viewState.getZTranslation() != child.getTranslationZ()
+ || viewState.getAlpha() != child.getAlpha()
|| viewState.height != child.getActualHeight()
|| viewState.clipTopAmount != child.getClipTopAmount())) {
mAnimationProperties.delay = mCurrentAdditionalDelay
@@ -191,7 +191,7 @@
mAnimationProperties.duration = ANIMATION_DURATION_APPEAR_DISAPPEAR + 50
+ (long) (100 * longerDurationFactor);
}
- child.setTranslationY(viewState.yTranslation + startOffset);
+ child.setTranslationY(viewState.getYTranslation() + startOffset);
}
}
@@ -400,7 +400,7 @@
// travelled
ExpandableViewState viewState =
((ExpandableView) event.viewAfterChangingView).getViewState();
- translationDirection = ((viewState.yTranslation
+ translationDirection = ((viewState.getYTranslation()
- (ownPosition + actualHeight / 2.0f)) * 2 /
actualHeight);
translationDirection = Math.max(Math.min(translationDirection, 1.0f),-1.0f);
@@ -433,7 +433,7 @@
ExpandableViewState viewState = changingView.getViewState();
mTmpState.copyFrom(viewState);
if (event.headsUpFromBottom) {
- mTmpState.yTranslation = mHeadsUpAppearHeightBottom;
+ mTmpState.setYTranslation(mHeadsUpAppearHeightBottom);
} else {
Runnable onAnimationEnd = null;
if (loggable) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index 786de29..d07da38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -21,6 +21,7 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
+import android.util.Log;
import android.util.Property;
import android.view.View;
import android.view.animation.Interpolator;
@@ -42,7 +43,7 @@
* A state of a view. This can be used to apply a set of view properties to a view with
* {@link com.android.systemui.statusbar.notification.stack.StackScrollState} or start
* animations with {@link com.android.systemui.statusbar.notification.stack.StackStateAnimator}.
-*/
+ */
public class ViewState implements Dumpable {
/**
@@ -51,6 +52,7 @@
*/
protected static final AnimationProperties NO_NEW_ANIMATIONS = new AnimationProperties() {
AnimationFilter mAnimationFilter = new AnimationFilter();
+
@Override
public AnimationFilter getAnimationFilter() {
return mAnimationFilter;
@@ -68,6 +70,7 @@
private static final int TAG_START_TRANSLATION_Y = R.id.translation_y_animator_start_value_tag;
private static final int TAG_START_TRANSLATION_Z = R.id.translation_z_animator_start_value_tag;
private static final int TAG_START_ALPHA = R.id.alpha_animator_start_value_tag;
+ private static final String LOG_TAG = "StackViewState";
private static final AnimatableProperty SCALE_X_PROPERTY
= new AnimatableProperty() {
@@ -117,35 +120,127 @@
}
};
- public float alpha;
- public float xTranslation;
- public float yTranslation;
- public float zTranslation;
public boolean gone;
public boolean hidden;
- public float scaleX = 1.0f;
- public float scaleY = 1.0f;
+
+ private float mAlpha;
+ private float mXTranslation;
+ private float mYTranslation;
+ private float mZTranslation;
+ private float mScaleX = 1.0f;
+ private float mScaleY = 1.0f;
+
+ public float getAlpha() {
+ return mAlpha;
+ }
+
+ /**
+ * @param alpha View transparency.
+ */
+ public void setAlpha(float alpha) {
+ if (isValidFloat(alpha, "alpha")) {
+ this.mAlpha = alpha;
+ }
+ }
+
+ public float getXTranslation() {
+ return mXTranslation;
+ }
+
+ /**
+ * @param xTranslation x-axis translation value for the animation.
+ */
+ public void setXTranslation(float xTranslation) {
+ if (isValidFloat(xTranslation, "xTranslation")) {
+ this.mXTranslation = xTranslation;
+ }
+ }
+
+ public float getYTranslation() {
+ return mYTranslation;
+ }
+
+ /**
+ * @param yTranslation y-axis translation value for the animation.
+ */
+ public void setYTranslation(float yTranslation) {
+ if (isValidFloat(yTranslation, "yTranslation")) {
+ this.mYTranslation = yTranslation;
+ }
+ }
+
+ public float getZTranslation() {
+ return mZTranslation;
+ }
+
+
+ /**
+ * @param zTranslation z-axis translation value for the animation.
+ */
+ public void setZTranslation(float zTranslation) {
+ if (isValidFloat(zTranslation, "zTranslation")) {
+ this.mZTranslation = zTranslation;
+ }
+ }
+
+ public float getScaleX() {
+ return mScaleX;
+ }
+
+ /**
+ * @param scaleX x-axis scale property for the animation.
+ */
+ public void setScaleX(float scaleX) {
+ if (isValidFloat(scaleX, "scaleX")) {
+ this.mScaleX = scaleX;
+ }
+ }
+
+ public float getScaleY() {
+ return mScaleY;
+ }
+
+ /**
+ * @param scaleY y-axis scale property for the animation.
+ */
+ public void setScaleY(float scaleY) {
+ if (isValidFloat(scaleY, "scaleY")) {
+ this.mScaleY = scaleY;
+ }
+ }
+
+ /**
+ * Checks if {@code value} is a valid float value. If it is not, logs it (using {@code name})
+ * and returns false.
+ */
+ private boolean isValidFloat(float value, String name) {
+ if (Float.isNaN(value)) {
+ Log.wtf(LOG_TAG, "Cannot set property " + name + " to NaN");
+ return false;
+ }
+ return true;
+ }
public void copyFrom(ViewState viewState) {
- alpha = viewState.alpha;
- xTranslation = viewState.xTranslation;
- yTranslation = viewState.yTranslation;
- zTranslation = viewState.zTranslation;
+ mAlpha = viewState.mAlpha;
+ mXTranslation = viewState.mXTranslation;
+ mYTranslation = viewState.mYTranslation;
+ mZTranslation = viewState.mZTranslation;
gone = viewState.gone;
hidden = viewState.hidden;
- scaleX = viewState.scaleX;
- scaleY = viewState.scaleY;
+ mScaleX = viewState.mScaleX;
+ mScaleY = viewState.mScaleY;
}
public void initFrom(View view) {
- alpha = view.getAlpha();
- xTranslation = view.getTranslationX();
- yTranslation = view.getTranslationY();
- zTranslation = view.getTranslationZ();
+ mAlpha = view.getAlpha();
+ mXTranslation = view.getTranslationX();
+ mYTranslation = view.getTranslationY();
+ mZTranslation = view.getTranslationZ();
gone = view.getVisibility() == View.GONE;
hidden = view.getVisibility() == View.INVISIBLE;
- scaleX = view.getScaleX();
- scaleY = view.getScaleY();
+ mScaleX = view.getScaleX();
+ mScaleY = view.getScaleY();
}
/**
@@ -161,51 +256,51 @@
boolean animatingX = isAnimating(view, TAG_ANIMATOR_TRANSLATION_X);
if (animatingX) {
updateAnimationX(view);
- } else if (view.getTranslationX() != this.xTranslation){
- view.setTranslationX(this.xTranslation);
+ } else if (view.getTranslationX() != this.mXTranslation) {
+ view.setTranslationX(this.mXTranslation);
}
// apply yTranslation
boolean animatingY = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y);
if (animatingY) {
updateAnimationY(view);
- } else if (view.getTranslationY() != this.yTranslation) {
- view.setTranslationY(this.yTranslation);
+ } else if (view.getTranslationY() != this.mYTranslation) {
+ view.setTranslationY(this.mYTranslation);
}
// apply zTranslation
boolean animatingZ = isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z);
if (animatingZ) {
updateAnimationZ(view);
- } else if (view.getTranslationZ() != this.zTranslation) {
- view.setTranslationZ(this.zTranslation);
+ } else if (view.getTranslationZ() != this.mZTranslation) {
+ view.setTranslationZ(this.mZTranslation);
}
// apply scaleX
boolean animatingScaleX = isAnimating(view, SCALE_X_PROPERTY);
if (animatingScaleX) {
- updateAnimation(view, SCALE_X_PROPERTY, scaleX);
- } else if (view.getScaleX() != scaleX) {
- view.setScaleX(scaleX);
+ updateAnimation(view, SCALE_X_PROPERTY, mScaleX);
+ } else if (view.getScaleX() != mScaleX) {
+ view.setScaleX(mScaleX);
}
// apply scaleY
boolean animatingScaleY = isAnimating(view, SCALE_Y_PROPERTY);
if (animatingScaleY) {
- updateAnimation(view, SCALE_Y_PROPERTY, scaleY);
- } else if (view.getScaleY() != scaleY) {
- view.setScaleY(scaleY);
+ updateAnimation(view, SCALE_Y_PROPERTY, mScaleY);
+ } else if (view.getScaleY() != mScaleY) {
+ view.setScaleY(mScaleY);
}
int oldVisibility = view.getVisibility();
- boolean becomesInvisible = this.alpha == 0.0f
+ boolean becomesInvisible = this.mAlpha == 0.0f
|| (this.hidden && (!isAnimating(view) || oldVisibility != View.VISIBLE));
boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
if (animatingAlpha) {
updateAlphaAnimation(view);
- } else if (view.getAlpha() != this.alpha) {
+ } else if (view.getAlpha() != this.mAlpha) {
// apply layer type
- boolean becomesFullyVisible = this.alpha == 1.0f;
+ boolean becomesFullyVisible = this.mAlpha == 1.0f;
boolean becomesFaded = !becomesInvisible && !becomesFullyVisible;
if (FadeOptimizedNotification.FADE_LAYER_OPTIMIZATION_ENABLED
&& view instanceof FadeOptimizedNotification) {
@@ -229,7 +324,7 @@
}
// apply alpha
- view.setAlpha(this.alpha);
+ view.setAlpha(this.mAlpha);
}
// apply visibility
@@ -274,54 +369,55 @@
/**
* Start an animation to this viewstate
- * @param child the view to animate
+ *
+ * @param child the view to animate
* @param animationProperties the properties of the animation
*/
public void animateTo(View child, AnimationProperties animationProperties) {
boolean wasVisible = child.getVisibility() == View.VISIBLE;
- final float alpha = this.alpha;
+ final float alpha = this.mAlpha;
if (!wasVisible && (alpha != 0 || child.getAlpha() != 0)
&& !this.gone && !this.hidden) {
child.setVisibility(View.VISIBLE);
}
float childAlpha = child.getAlpha();
- boolean alphaChanging = this.alpha != childAlpha;
+ boolean alphaChanging = this.mAlpha != childAlpha;
if (child instanceof ExpandableView) {
// We don't want views to change visibility when they are animating to GONE
alphaChanging &= !((ExpandableView) child).willBeGone();
}
// start translationX animation
- if (child.getTranslationX() != this.xTranslation) {
+ if (child.getTranslationX() != this.mXTranslation) {
startXTranslationAnimation(child, animationProperties);
} else {
abortAnimation(child, TAG_ANIMATOR_TRANSLATION_X);
}
// start translationY animation
- if (child.getTranslationY() != this.yTranslation) {
+ if (child.getTranslationY() != this.mYTranslation) {
startYTranslationAnimation(child, animationProperties);
} else {
abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Y);
}
// start translationZ animation
- if (child.getTranslationZ() != this.zTranslation) {
+ if (child.getTranslationZ() != this.mZTranslation) {
startZTranslationAnimation(child, animationProperties);
} else {
abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Z);
}
// start scaleX animation
- if (child.getScaleX() != scaleX) {
- PropertyAnimator.startAnimation(child, SCALE_X_PROPERTY, scaleX, animationProperties);
+ if (child.getScaleX() != mScaleX) {
+ PropertyAnimator.startAnimation(child, SCALE_X_PROPERTY, mScaleX, animationProperties);
} else {
abortAnimation(child, SCALE_X_PROPERTY.getAnimatorTag());
}
// start scaleX animation
- if (child.getScaleY() != scaleY) {
- PropertyAnimator.startAnimation(child, SCALE_Y_PROPERTY, scaleY, animationProperties);
+ if (child.getScaleY() != mScaleY) {
+ PropertyAnimator.startAnimation(child, SCALE_Y_PROPERTY, mScaleY, animationProperties);
} else {
abortAnimation(child, SCALE_Y_PROPERTY.getAnimatorTag());
}
@@ -329,7 +425,7 @@
// start alpha animation
if (alphaChanging) {
startAlphaAnimation(child, animationProperties);
- } else {
+ } else {
abortAnimation(child, TAG_ANIMATOR_ALPHA);
}
}
@@ -339,9 +435,9 @@
}
private void startAlphaAnimation(final View child, AnimationProperties properties) {
- Float previousStartValue = getChildTag(child,TAG_START_ALPHA);
- Float previousEndValue = getChildTag(child,TAG_END_ALPHA);
- final float newEndValue = this.alpha;
+ Float previousStartValue = getChildTag(child, TAG_START_ALPHA);
+ Float previousEndValue = getChildTag(child, TAG_END_ALPHA);
+ final float newEndValue = this.mAlpha;
if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
@@ -426,9 +522,9 @@
}
private void startZTranslationAnimation(final View child, AnimationProperties properties) {
- Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Z);
- Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
- float newEndValue = this.zTranslation;
+ Float previousStartValue = getChildTag(child, TAG_START_TRANSLATION_Z);
+ Float previousEndValue = getChildTag(child, TAG_END_TRANSLATION_Z);
+ float newEndValue = this.mZTranslation;
if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
@@ -487,9 +583,9 @@
}
private void startXTranslationAnimation(final View child, AnimationProperties properties) {
- Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_X);
- Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_X);
- float newEndValue = this.xTranslation;
+ Float previousStartValue = getChildTag(child, TAG_START_TRANSLATION_X);
+ Float previousEndValue = getChildTag(child, TAG_END_TRANSLATION_X);
+ float newEndValue = this.mXTranslation;
if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
@@ -519,7 +615,7 @@
child.getTranslationX(), newEndValue);
Interpolator customInterpolator = properties.getCustomInterpolator(child,
View.TRANSLATION_X);
- Interpolator interpolator = customInterpolator != null ? customInterpolator
+ Interpolator interpolator = customInterpolator != null ? customInterpolator
: Interpolators.FAST_OUT_SLOW_IN;
animator.setInterpolator(interpolator);
long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
@@ -553,9 +649,9 @@
}
private void startYTranslationAnimation(final View child, AnimationProperties properties) {
- Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Y);
- Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
- float newEndValue = this.yTranslation;
+ Float previousStartValue = getChildTag(child, TAG_START_TRANSLATION_Y);
+ Float previousEndValue = getChildTag(child, TAG_END_TRANSLATION_Y);
+ float newEndValue = this.mYTranslation;
if (previousEndValue != null && previousEndValue == newEndValue) {
return;
}
@@ -585,7 +681,7 @@
child.getTranslationY(), newEndValue);
Interpolator customInterpolator = properties.getCustomInterpolator(child,
View.TRANSLATION_Y);
- Interpolator interpolator = customInterpolator != null ? customInterpolator
+ Interpolator interpolator = customInterpolator != null ? customInterpolator
: Interpolators.FAST_OUT_SLOW_IN;
animator.setInterpolator(interpolator);
long newDuration = cancelAnimatorAndGetNewDuration(properties.duration, previousAnimator);
@@ -644,7 +740,7 @@
/**
* Cancel the previous animator and get the duration of the new animation.
*
- * @param duration the new duration
+ * @param duration the new duration
* @param previousAnimator the animator which was running before
* @return the new duration
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 5a70d89..9767103 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -211,11 +211,11 @@
canvas.drawLine(end, 0, end, height, paint);
paint.setColor(Color.GREEN);
- int lastIcon = (int) mLastVisibleIconState.xTranslation;
+ int lastIcon = (int) mLastVisibleIconState.getXTranslation();
canvas.drawLine(lastIcon, 0, lastIcon, height, paint);
if (mFirstVisibleIconState != null) {
- int firstIcon = (int) mFirstVisibleIconState.xTranslation;
+ int firstIcon = (int) mFirstVisibleIconState.getXTranslation();
canvas.drawLine(firstIcon, 0, firstIcon, height, paint);
}
@@ -413,7 +413,7 @@
View view = getChildAt(i);
ViewState iconState = mIconStates.get(view);
iconState.initFrom(view);
- iconState.alpha = mIsolatedIcon == null || view == mIsolatedIcon ? 1.0f : 0.0f;
+ iconState.setAlpha(mIsolatedIcon == null || view == mIsolatedIcon ? 1.0f : 0.0f);
iconState.hidden = false;
}
}
@@ -467,7 +467,7 @@
// We only modify the xTranslation if it's fully inside of the container
// since during the transition to the shelf, the translations are controlled
// from the outside
- iconState.xTranslation = translationX;
+ iconState.setXTranslation(translationX);
}
if (mFirstVisibleIconState == null) {
mFirstVisibleIconState = iconState;
@@ -501,7 +501,7 @@
View view = getChildAt(i);
IconState iconState = mIconStates.get(view);
int dotWidth = mStaticDotDiameter + mDotPadding;
- iconState.xTranslation = translationX;
+ iconState.setXTranslation(translationX);
if (mNumDots < MAX_DOTS) {
if (mNumDots == 0 && iconState.iconAppearAmount < 0.8f) {
iconState.visibleState = StatusBarIconView.STATE_ICON;
@@ -525,7 +525,8 @@
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
IconState iconState = mIconStates.get(view);
- iconState.xTranslation = getWidth() - iconState.xTranslation - view.getWidth();
+ iconState.setXTranslation(
+ getWidth() - iconState.getXTranslation() - view.getWidth());
}
}
if (mIsolatedIcon != null) {
@@ -533,8 +534,8 @@
if (iconState != null) {
// Most of the time the icon isn't yet added when this is called but only happening
// later
- iconState.xTranslation = mIsolatedIconLocation.left - mAbsolutePosition[0]
- - (1 - mIsolatedIcon.getIconScale()) * mIsolatedIcon.getWidth() / 2.0f;
+ iconState.setXTranslation(mIsolatedIconLocation.left - mAbsolutePosition[0]
+ - (1 - mIsolatedIcon.getIconScale()) * mIsolatedIcon.getWidth() / 2.0f);
iconState.visibleState = StatusBarIconView.STATE_ICON;
}
}
@@ -609,8 +610,10 @@
return 0;
}
- int translation = (int) (isLayoutRtl() ? getWidth() - mLastVisibleIconState.xTranslation
- : mLastVisibleIconState.xTranslation + mIconSize);
+ int translation = (int) (isLayoutRtl()
+ ? getWidth() - mLastVisibleIconState.getXTranslation()
+ : mLastVisibleIconState.getXTranslation() + mIconSize);
+
// There's a chance that last translation goes beyond the edge maybe
return Math.min(getWidth(), translation);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index d464acb..26c1767 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -337,7 +337,7 @@
// without cutting off the child view.
translationX -= getViewTotalWidth(child);
childState.visibleState = STATE_ICON;
- childState.xTranslation = translationX;
+ childState.setXTranslation(translationX);
mLayoutStates.add(0, childState);
// Shift translationX over by mIconSpacing for the next view.
@@ -354,13 +354,13 @@
for (int i = totalVisible - 1; i >= 0; i--) {
StatusIconState state = mLayoutStates.get(i);
// Allow room for underflow if we found we need it in onMeasure
- if (mNeedsUnderflow && (state.xTranslation < (contentStart + mUnderflowWidth))||
- (mShouldRestrictIcons && visible >= maxVisible)) {
+ if (mNeedsUnderflow && (state.getXTranslation() < (contentStart + mUnderflowWidth))
+ || (mShouldRestrictIcons && (visible >= maxVisible))) {
firstUnderflowIndex = i;
break;
}
mUnderflowStart = (int) Math.max(
- contentStart, state.xTranslation - mUnderflowWidth - mIconSpacing);
+ contentStart, state.getXTranslation() - mUnderflowWidth - mIconSpacing);
visible++;
}
@@ -371,7 +371,7 @@
for (int i = firstUnderflowIndex; i >= 0; i--) {
StatusIconState state = mLayoutStates.get(i);
if (totalDots < MAX_DOTS) {
- state.xTranslation = dotOffset;
+ state.setXTranslation(dotOffset);
state.visibleState = STATE_DOT;
dotOffset -= dotWidth;
totalDots++;
@@ -386,7 +386,7 @@
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
StatusIconState state = getViewStateFromChild(child);
- state.xTranslation = width - state.xTranslation - child.getWidth();
+ state.setXTranslation(width - state.getXTranslation() - child.getWidth());
}
}
}
@@ -410,7 +410,7 @@
}
vs.initFrom(child);
- vs.alpha = 1.0f;
+ vs.setAlpha(1.0f);
vs.hidden = false;
}
}
@@ -442,7 +442,7 @@
parentWidth = ((View) view.getParent()).getWidth();
}
- float currentDistanceToEnd = parentWidth - xTranslation;
+ float currentDistanceToEnd = parentWidth - getXTranslation();
if (!(view instanceof StatusIconDisplayable)) {
return;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
new file mode 100644
index 0000000..da543d4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification.stack
+
+import android.testing.AndroidTestingRunner
+import android.util.Log
+import android.util.Log.TerribleFailureHandler
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import kotlin.math.log2
+import kotlin.math.sqrt
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ViewStateTest : SysuiTestCase() {
+ private val viewState = ViewState()
+
+ private var wtfHandler: TerribleFailureHandler? = null
+ private var wtfCount = 0
+
+ @Suppress("DIVISION_BY_ZERO")
+ @Test
+ fun testWtfs() {
+ interceptWtfs()
+
+ // Setting valid values doesn't cause any wtfs.
+ viewState.alpha = 0.1f
+ viewState.xTranslation = 0f
+ viewState.yTranslation = 10f
+ viewState.zTranslation = 20f
+ viewState.scaleX = 0.5f
+ viewState.scaleY = 0.25f
+
+ expectWtfs(0)
+
+ // Setting NaN values leads to wtfs being logged, and the value not being changed.
+ viewState.alpha = 0.0f / 0.0f
+ expectWtfs(1)
+ Assert.assertEquals(viewState.alpha, 0.1f)
+
+ viewState.xTranslation = Float.NaN
+ expectWtfs(2)
+ Assert.assertEquals(viewState.xTranslation, 0f)
+
+ viewState.yTranslation = log2(-10.0).toFloat()
+ expectWtfs(3)
+ Assert.assertEquals(viewState.yTranslation, 10f)
+
+ viewState.zTranslation = sqrt(-1.0).toFloat()
+ expectWtfs(4)
+ Assert.assertEquals(viewState.zTranslation, 20f)
+
+ viewState.scaleX = Float.POSITIVE_INFINITY + Float.NEGATIVE_INFINITY
+ expectWtfs(5)
+ Assert.assertEquals(viewState.scaleX, 0.5f)
+
+ viewState.scaleY = Float.POSITIVE_INFINITY * 0
+ expectWtfs(6)
+ Assert.assertEquals(viewState.scaleY, 0.25f)
+ }
+
+ private fun interceptWtfs() {
+ wtfCount = 0
+ wtfHandler =
+ Log.setWtfHandler { _: String?, e: Log.TerribleFailure, _: Boolean ->
+ Log.e("ViewStateTest", "Observed WTF: $e")
+ wtfCount++
+ }
+ }
+
+ private fun expectWtfs(expectedWtfCount: Int) {
+ Assert.assertNotNull(wtfHandler)
+ Assert.assertEquals(expectedWtfCount, wtfCount)
+ }
+}