diff options
| author | 2016-11-29 15:42:34 -0800 | |
|---|---|---|
| committer | 2016-12-07 15:57:44 -0800 | |
| commit | 65d418ec8957fb1af03a8cc68aed90744a5848ff (patch) | |
| tree | 3392ad852f7ee61758def70351a7112726a8f434 | |
| parent | 5ea19572afe9955555f73a24f0b18f7eb5727bdf (diff) | |
Improved the performance of the notification shelf
The shelf had a few inefficiencies that were adding up
when calculating the positions.
Test: runtest systemui-jank -c android.platform.systemui.tests.jank.SystemUiJankTests -m testNotificationListPull_manyNotifications
Bug: 32437839
Change-Id: Iac08a7c364a924f1d0c14258461383b431f0542b
6 files changed, 85 insertions, 60 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 173f160a70d7..d4b478a87451 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -103,7 +103,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private boolean mDimmed; private boolean mDark; - private int mBgTint = 0; + private int mBgTint = NO_COLOR; private float mBgAlpha = 1f; /** @@ -481,8 +481,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView * Sets the tint color of the background */ public void setTintColor(int color, boolean animated) { - mBgTint = color; - updateBackgroundTint(animated); + if (color != mBgTint) { + mBgTint = color; + updateBackgroundTint(animated); + } } /** @@ -541,13 +543,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } private void setBackgroundTintColor(int color) { - mCurrentBackgroundTint = color; - if (color == mNormalColor) { - // We don't need to tint a normal notification - color = 0; + if (color != mCurrentBackgroundTint) { + mCurrentBackgroundTint = color; + if (color == mNormalColor) { + // We don't need to tint a normal notification + color = 0; + } + mBackgroundDimmed.setTint(color); + mBackgroundNormal.setTint(color); } - mBackgroundDimmed.setTint(color); - mBackgroundNormal.setTint(color); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index e4654e608d09..996e2ef587f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -1685,13 +1685,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { @Override public void setClipBottomAmount(int clipBottomAmount) { - super.setClipBottomAmount(clipBottomAmount); - mPrivateLayout.setClipBottomAmount(clipBottomAmount); - mPublicLayout.setClipBottomAmount(clipBottomAmount); - if (mGuts != null) { - mGuts.setClipBottomAmount(clipBottomAmount); + if (clipBottomAmount != mClipBottomAmount) { + super.setClipBottomAmount(clipBottomAmount); + mPrivateLayout.setClipBottomAmount(clipBottomAmount); + mPublicLayout.setClipBottomAmount(clipBottomAmount); + if (mGuts != null) { + mGuts.setClipBottomAmount(clipBottomAmount); + } } if (mChildrenContainer != null) { + // We have to update this even if it hasn't changed, since the children locations can + // have changed mChildrenContainer.setClipBottomAmount(clipBottomAmount); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 0138ca86c3d3..80d41883066e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -37,8 +37,6 @@ import com.android.systemui.statusbar.stack.ExpandableViewState; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.stack.StackScrollState; -import java.util.WeakHashMap; - /** * A notification shelf view that is placed inside the notification scroller. It manages the * overflow icons that don't fit into the regular list anymore. @@ -165,6 +163,7 @@ public class NotificationShelf extends ActivatableNotificationView { mShelfState.notGoneIndex = Math.min(mShelfState.notGoneIndex, mNotGoneIndex); } mShelfState.hasItemsInStableShelf = lastViewState.inShelf; + mShelfState.hidden = !mAmbientState.isShadeExpanded(); } else { mShelfState.hidden = true; mShelfState.location = ExpandableViewState.LOCATION_GONE; @@ -177,15 +176,15 @@ public class NotificationShelf extends ActivatableNotificationView { * the icons from the notification area into the shelf. */ public void updateAppearance() { - WeakHashMap<View, NotificationIconContainer.IconState> iconStates = - mShelfIcons.resetViewStates(); + mShelfIcons.resetViewStates(); + float shelfStart = getTranslationY(); float numViewsInShelf = 0.0f; View lastChild = mAmbientState.getLastVisibleBackgroundChild(); mNotGoneIndex = -1; float interpolationStart = mMaxLayoutHeight - getIntrinsicHeight() * 2; float expandAmount = 0.0f; - if (getTranslationY() >= interpolationStart) { - expandAmount = (getTranslationY() - interpolationStart) / getIntrinsicHeight(); + if (shelfStart >= interpolationStart) { + expandAmount = (shelfStart - interpolationStart) / getIntrinsicHeight(); expandAmount = Math.min(1.0f, expandAmount); } // find the first view that doesn't overlap with the shelf @@ -199,6 +198,7 @@ public class NotificationShelf extends ActivatableNotificationView { int colorTwoBefore = NO_COLOR; int previousColor = NO_COLOR; float transitionAmount = 0.0f; + int baseZHeight = mAmbientState.getBaseZHeight(); while (notificationIndex < mHostLayout.getChildCount()) { ExpandableView child = (ExpandableView) mHostLayout.getChildAt(notificationIndex); notificationIndex++; @@ -208,26 +208,26 @@ public class NotificationShelf extends ActivatableNotificationView { } ExpandableNotificationRow row = (ExpandableNotificationRow) child; float notificationClipEnd; - float shelfStart = getTranslationY(); - boolean aboveShelf = row.getTranslationZ() > mAmbientState.getBaseZHeight(); + boolean aboveShelf = row.getTranslationZ() > baseZHeight; boolean isLastChild = child == lastChild; + float rowTranslationY = row.getTranslationY(); if (isLastChild || aboveShelf || backgroundForceHidden) { notificationClipEnd = shelfStart + getIntrinsicHeight(); } else { notificationClipEnd = shelfStart - mPaddingBetweenElements; - float height = notificationClipEnd - row.getTranslationY(); + float height = notificationClipEnd - rowTranslationY; if (!row.isBelowSpeedBump() && height <= getNotificationMergeSize()) { // We want the gap to close when we reached the minimum size and only shrink // before notificationClipEnd = Math.min(shelfStart, - row.getTranslationY() + getNotificationMergeSize()); + rowTranslationY + getNotificationMergeSize()); } } updateNotificationClipHeight(row, notificationClipEnd); float inShelfAmount = updateIconAppearance(row, expandAmount, isLastChild); numViewsInShelf += inShelfAmount; int ownColorUntinted = row.getBackgroundColorWithoutTint(); - if (row.getTranslationY() >= getTranslationY() && mNotGoneIndex == -1) { + if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) { mNotGoneIndex = notGoneIndex; setTintColor(previousColor); setOverrideTintColor(colorTwoBefore, transitionAmount); @@ -250,9 +250,6 @@ public class NotificationShelf extends ActivatableNotificationView { } mShelfIcons.calculateIconTranslations(); mShelfIcons.applyIconStates(); - setVisibility(mAmbientState.isShadeExpanded() - ? VISIBLE - : INVISIBLE); boolean hideBackground = numViewsInShelf < 1.0f; setHideBackground(hideBackground || backgroundForceHidden); if (mNotGoneIndex == -1) { @@ -441,9 +438,11 @@ public class NotificationShelf extends ActivatableNotificationView { } private void setHideBackground(boolean hideBackground) { - mHideBackground = hideBackground; - updateBackground(); - updateOutline(); + if (mHideBackground != hideBackground) { + mHideBackground = hideBackground; + updateBackground(); + updateOutline(); + } } public boolean hidesBackground() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 2621e4a50931..6650e7271b28 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -455,6 +455,7 @@ public class StatusBarIconView extends AnimatedImageView { } public void setVisibleState(int visibleState, boolean animate, Runnable endRunnable) { + boolean runnableAdded = false; if (visibleState != mVisibleState) { mVisibleState = visibleState; if (animate) { @@ -467,20 +468,22 @@ public class StatusBarIconView extends AnimatedImageView { targetAmount = 1.0f; interpolator = Interpolators.LINEAR_OUT_SLOW_IN; } - mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT, - targetAmount); - mIconAppearAnimator.setInterpolator(interpolator); - mIconAppearAnimator.setDuration(100); - mIconAppearAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mIconAppearAnimator = null; - if (endRunnable != null) { - endRunnable.run(); + float currentAmount = getIconAppearAmount(); + if (targetAmount != currentAmount) { + mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT, + currentAmount, targetAmount); + mIconAppearAnimator.setInterpolator(interpolator); + mIconAppearAnimator.setDuration(100); + mIconAppearAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIconAppearAnimator = null; + runRunnable(endRunnable); } - } - }); - mIconAppearAnimator.start(); + }); + mIconAppearAnimator.start(); + runnableAdded = true; + } if (mDotAnimator != null) { mDotAnimator.cancel(); @@ -491,22 +494,39 @@ public class StatusBarIconView extends AnimatedImageView { targetAmount = 1.0f; interpolator = Interpolators.LINEAR_OUT_SLOW_IN; } - mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT, - targetAmount); - mDotAnimator.setInterpolator(interpolator); - mDotAnimator.setDuration(100); - mDotAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mDotAnimator = null; - } - }); - mDotAnimator.start(); + currentAmount = getDotAppearAmount(); + if (targetAmount != currentAmount) { + mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT, + currentAmount, targetAmount); + mDotAnimator.setInterpolator(interpolator); + mDotAnimator.setDuration(100); + final boolean runRunnable = !runnableAdded; + mDotAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mDotAnimator = null; + if (runRunnable) { + runRunnable(endRunnable); + } + } + }); + mDotAnimator.start(); + runnableAdded = true; + } } else { setIconAppearAmount(visibleState == STATE_ICON ? 1.0f : 0.0f); setDotAppearAmount(visibleState == STATE_DOT ? 1.0f : 0.0f); } } + if (!runnableAdded) { + runRunnable(endRunnable); + } + } + + private void runRunnable(Runnable runnable) { + if (runnable != null) { + runnable.run(); + } } public void setIconAppearAmount(float iconAppearAmount) { 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 160b23384740..294058474d15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -31,7 +31,7 @@ import com.android.systemui.statusbar.stack.AnimationFilter; import com.android.systemui.statusbar.stack.AnimationProperties; import com.android.systemui.statusbar.stack.ViewState; -import java.util.WeakHashMap; +import java.util.HashMap; /** * A container for notification icons. It handles overflowing icons properly and positions them @@ -80,7 +80,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { }.setDuration(200).setDelay(50); private boolean mShowAllIcons = true; - private WeakHashMap<View, IconState> mIconStates = new WeakHashMap<>(); + private final HashMap<View, IconState> mIconStates = new HashMap<>(); private int mDotPadding; private int mStaticDotRadius; private int mActualLayoutWidth = -1; @@ -200,14 +200,13 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { return getChildCount(); } - public WeakHashMap<View, IconState> resetViewStates() { + public void resetViewStates() { for (int i = 0; i < getChildCount(); i++) { View view = getChildAt(i); ViewState iconState = mIconStates.get(view); iconState.initFrom(view); iconState.alpha = 1.0f; } - return mIconStates; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 10d995ccadb5..4fb982b1f26b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -715,7 +715,6 @@ public class NotificationStackScrollLayout extends ViewGroup requestChildrenUpdate(); } setStackTranslation(translationY); - requestChildrenUpdate(); } private void setRequestedClipBounds(Rect clipRect) { |