diff options
| author | 2022-10-10 14:18:37 +0000 | |
|---|---|---|
| committer | 2022-10-10 14:18:37 +0000 | |
| commit | b65bc409a9a00b9ead02be28c4954893dc26c10c (patch) | |
| tree | 4e222d610f2fe1cf9c1da9c67081b1fb56dac707 | |
| parent | da56b4d9b643eb34ae2d300fc002fdf31737e8e1 (diff) | |
| parent | 40838e9b7dcf60a1bceda72117cc88166dff05bc (diff) | |
Merge "Log.wtf when float properties in ViewState are set to NaN." into tm-qpr-dev
11 files changed, 372 insertions, 173 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index d67f94f11e65..f96198450ed6 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 @@ public class NotificationShelf extends ActivatableNotificationView implements 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 @@ public class NotificationShelf extends ActivatableNotificationView implements } 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 @@ public class NotificationShelf extends ActivatableNotificationView implements 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 @@ public class NotificationShelf extends ActivatableNotificationView implements // 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 07ed0135bf6e..087dc71f6cf2 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView 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 1e09b8a37645..38f0c550d4fc 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 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { // 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 d77e03fd043d..7b23a56af836 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 @@ public class NotificationChildrenContainer extends ViewGroup 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 @@ public class NotificationChildrenContainer extends ViewGroup 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 @@ public class NotificationChildrenContainer extends ViewGroup 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 @@ public class NotificationChildrenContainer extends ViewGroup // 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 @@ public class NotificationChildrenContainer extends ViewGroup // 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 @@ public class NotificationChildrenContainer extends ViewGroup 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 6821b141d140..836cacc185c6 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 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @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 32591ce733b9..8d28f7524f9a 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { // 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { + 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { } } 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 @@ public class StackScrollAlgorithm { // 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { 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 174bf4c27de8..ee72943bef57 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 @@ public class StackStateAnimator { 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 @@ public class StackStateAnimator { mAnimationProperties.duration = ANIMATION_DURATION_APPEAR_DISAPPEAR + 50 + (long) (100 * longerDurationFactor); } - child.setTranslationY(viewState.yTranslation + startOffset); + child.setTranslationY(viewState.getYTranslation() + startOffset); } } @@ -400,7 +400,7 @@ public class StackStateAnimator { // 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 @@ public class StackStateAnimator { 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 786de29a5819..d07da381a186 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.AnimatorListenerAdapter; 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 @@ import java.lang.reflect.Modifier; * 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 @@ public class ViewState implements Dumpable { */ protected static final AnimationProperties NO_NEW_ANIMATIONS = new AnimationProperties() { AnimationFilter mAnimationFilter = new AnimationFilter(); + @Override public AnimationFilter getAnimationFilter() { return mAnimationFilter; @@ -68,6 +70,7 @@ public class ViewState implements Dumpable { 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 class ViewState implements Dumpable { } }; - 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 @@ public class ViewState implements Dumpable { 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 @@ public class ViewState implements Dumpable { } // apply alpha - view.setAlpha(this.alpha); + view.setAlpha(this.mAlpha); } // apply visibility @@ -274,54 +369,55 @@ public class ViewState implements Dumpable { /** * 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 @@ public class ViewState implements Dumpable { // start alpha animation if (alphaChanging) { startAlphaAnimation(child, animationProperties); - } else { + } else { abortAnimation(child, TAG_ANIMATOR_ALPHA); } } @@ -339,9 +435,9 @@ public class ViewState implements Dumpable { } 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 @@ public class ViewState implements Dumpable { } 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 @@ public class ViewState implements Dumpable { } 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 @@ public class ViewState implements Dumpable { 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 @@ public class ViewState implements Dumpable { } 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 @@ public class ViewState implements Dumpable { 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 @@ public class ViewState implements Dumpable { /** * 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 5a70d89908f8..976710351a44 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 @@ public class NotificationIconContainer extends ViewGroup { 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 @@ public class NotificationIconContainer extends ViewGroup { 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 @@ public class NotificationIconContainer extends ViewGroup { // 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 @@ public class NotificationIconContainer extends ViewGroup { 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 @@ public class NotificationIconContainer extends ViewGroup { 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 @@ public class NotificationIconContainer extends ViewGroup { 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 @@ public class NotificationIconContainer extends ViewGroup { 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 d464acb7fe76..26c17674ab10 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 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { // 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 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { 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 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { 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 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { 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 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { } vs.initFrom(child); - vs.alpha = 1.0f; + vs.setAlpha(1.0f); vs.hidden = false; } } @@ -442,7 +442,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout { 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 000000000000..da543d4454b8 --- /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) + } +} |