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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -715,7 +715,6 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
requestChildrenUpdate();
|
||||
}
|
||||
setStackTranslation(translationY);
|
||||
requestChildrenUpdate();
|
||||
}
|
||||
|
||||
private void setRequestedClipBounds(Rect clipRect) {
|
||||
|
||||
Reference in New Issue
Block a user