Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65d418ec authored by Selim Cinek's avatar Selim Cinek
Browse files

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
parent 5ea19572
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -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,9 +481,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
     * Sets the tint color of the background
     */
    public void setTintColor(int color, boolean animated) {
        if (color != mBgTint) {
            mBgTint = color;
            updateBackgroundTint(animated);
        }
    }

    /**
     * Set an override tint color that is used for the background.
@@ -541,6 +543,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
    }

    private void setBackgroundTintColor(int color) {
        if (color != mCurrentBackgroundTint) {
            mCurrentBackgroundTint = color;
            if (color == mNormalColor) {
                // We don't need to tint a normal notification
@@ -549,6 +552,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
            mBackgroundDimmed.setTint(color);
            mBackgroundNormal.setTint(color);
        }
    }

    /**
     * Fades in the background when exiting dark mode.
+9 −5
Original line number Diff line number Diff line
@@ -1685,13 +1685,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {

    @Override
    public void setClipBottomAmount(int 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);
        }
    }
+16 −17
Original line number Diff line number Diff line
@@ -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();
        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,10 +438,12 @@ public class NotificationShelf extends ActivatableNotificationView {
    }

    private void setHideBackground(boolean hideBackground) {
        if (mHideBackground != hideBackground) {
            mHideBackground = hideBackground;
            updateBackground();
            updateOutline();
        }
    }

    public boolean hidesBackground() {
        return mHideBackground;
+44 −24
Original line number Diff line number Diff line
@@ -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;
                }
                float currentAmount = getIconAppearAmount();
                if (targetAmount != currentAmount) {
                    mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT,
                        targetAmount);
                            currentAmount, targetAmount);
                    mIconAppearAnimator.setInterpolator(interpolator);
                    mIconAppearAnimator.setDuration(100);
                    mIconAppearAnimator.addListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            mIconAppearAnimator = null;
                        if (endRunnable != null) {
                            endRunnable.run();
                        }
                            runRunnable(endRunnable);
                        }
                    });
                    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;
                }
                currentAmount = getDotAppearAmount();
                if (targetAmount != currentAmount) {
                    mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT,
                        targetAmount);
                            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) {
+3 −4
Original line number Diff line number Diff line
@@ -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;
    }

    /**
Loading