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

Commit ed86a623 authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Fix weird shelf truncation when only media can show.

The root cause of the rendering issue was that the NotificationShelf's NotificationBackgroundView had an mBackgroundTop value of -5 which caused its shape to be truncated. This was a feature that was part of the old dyson animation (when transitioning from the statusBar to the shelf when pulling down the shade) that is no longer needed, and which was causing this bug that only became visible given the more rounded corners.

This CL removes a bunch of unused code:
* The NotificationShelf's firstElementRoundness was set but never used, and could be trivially deleted.
* setBackgroundTop() on ExpandableOutlineView was only called on NotificationShelf instances, but it was overridden by ActivatableNotificationRow.
* The only place where ActivatableNotificationRow.setBackgroundTop() was called was the the deleted logic in the shelf.  This feature seems to have been related to the initial phases of the StatusBar-to-shade dyson animation which used to exist on R, but has been removed.
* NotificationBackgroundView.setBackgroundTop() was only used by the last method, so it could be deleted.

I also added some developer-toggleable dump() improvements for ExpandableView and its subclasses.  Note that ExpandableNotificationRow simply does not call these superclass methods.  Regardless, these intermediate subclasses do print information for NotificationShelf and NotificationFooter and other similar views.  These dumps allowed me to diagnose the root cause of this bug, but do not provide sufficient value to merit includion in the bugreport.  The only exception to that is that I left the new Roundness dump from ExpandableOutlineView, since that does indeed apply, and was not previously printed.

Fixes: 236091099
Test: set the config resource keyguard_max_notification_count to 1, show media on lockscreen.
Change-Id: I4ff4c72e542aefd993322bcc54b174ebc086c404
parent ef056c36
Loading
Loading
Loading
Loading
+17 −25
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.IndentingPrintWriter;
import android.util.MathUtils;
import android.util.MathUtils;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
@@ -52,6 +53,9 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.util.DumpUtilsKt;

import java.io.PrintWriter;


/**
/**
 * A notification shelf view that is placed inside the notification scroller. It manages the
 * A notification shelf view that is placed inside the notification scroller. It manages the
@@ -86,7 +90,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
    private boolean mInteractive;
    private boolean mInteractive;
    private boolean mAnimationsEnabled = true;
    private boolean mAnimationsEnabled = true;
    private boolean mShowNotificationShelf;
    private boolean mShowNotificationShelf;
    private float mFirstElementRoundness;
    private Rect mClipRect = new Rect();
    private Rect mClipRect = new Rect();
    private int mIndexOfFirstViewInShelf = -1;
    private int mIndexOfFirstViewInShelf = -1;
    private float mCornerAnimationDistance;
    private float mCornerAnimationDistance;
@@ -263,8 +266,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
        final float actualWidth = mAmbientState.isOnKeyguard()
        final float actualWidth = mAmbientState.isOnKeyguard()
                ? MathUtils.lerp(shortestWidth, getWidth(), fractionToShade)
                ? MathUtils.lerp(shortestWidth, getWidth(), fractionToShade)
                : getWidth();
                : getWidth();
        ActivatableNotificationView anv = (ActivatableNotificationView) this;
        setBackgroundWidth((int) actualWidth);
        anv.setBackgroundWidth((int) actualWidth);
        if (mShelfIcons != null) {
        if (mShelfIcons != null) {
            mShelfIcons.setActualLayoutWidth((int) actualWidth);
            mShelfIcons.setActualLayoutWidth((int) actualWidth);
        }
        }
@@ -365,9 +367,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
        boolean expandingAnimated = mAmbientState.isExpansionChanging()
        boolean expandingAnimated = mAmbientState.isExpansionChanging()
                && !mAmbientState.isPanelTracking();
                && !mAmbientState.isPanelTracking();
        int baseZHeight = mAmbientState.getBaseZHeight();
        int baseZHeight = mAmbientState.getBaseZHeight();
        int backgroundTop = 0;
        int clipTopAmount = 0;
        int clipTopAmount = 0;
        float firstElementRoundness = 0.0f;


        for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
        for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
            ExpandableView child = mHostLayoutController.getChildAt(i);
            ExpandableView child = mHostLayoutController.getChildAt(i);
@@ -420,18 +420,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
                if (notGoneIndex != 0 || !aboveShelf) {
                if (notGoneIndex != 0 || !aboveShelf) {
                    expandableRow.setAboveShelf(false);
                    expandableRow.setAboveShelf(false);
                }
                }
                if (notGoneIndex == 0) {
                    StatusBarIconView icon = expandableRow.getEntry().getIcons().getShelfIcon();
                    NotificationIconContainer.IconState iconState = getIconState(icon);
                    // The icon state might be null in rare cases where the notification is actually
                    // added to the layout, but not to the shelf. An example are replied messages,
                    // since they don't show up on AOD
                    if (iconState != null && iconState.clampedAppearAmount == 1.0f) {
                        // only if the first icon is fully in the shelf we want to clip to it!
                        backgroundTop = (int) (child.getTranslationY() - getTranslationY());
                        firstElementRoundness = expandableRow.getTopRoundness();
                    }
                }


                previousColor = ownColorUntinted;
                previousColor = ownColorUntinted;
                notGoneIndex++;
                notGoneIndex++;
@@ -467,8 +455,6 @@ public class NotificationShelf extends ActivatableNotificationView implements


        // TODO(b/172289889) transition last icon in shelf to notification icon and vice versa.
        // TODO(b/172289889) transition last icon in shelf to notification icon and vice versa.
        setVisibility(isHidden ? View.INVISIBLE : View.VISIBLE);
        setVisibility(isHidden ? View.INVISIBLE : View.VISIBLE);
        setBackgroundTop(backgroundTop);
        setFirstElementRoundness(firstElementRoundness);
        mShelfIcons.setSpeedBumpIndex(mHostLayoutController.getSpeedBumpIndex());
        mShelfIcons.setSpeedBumpIndex(mHostLayoutController.getSpeedBumpIndex());
        mShelfIcons.calculateIconXTranslations();
        mShelfIcons.calculateIconXTranslations();
        mShelfIcons.applyIconStates();
        mShelfIcons.applyIconStates();
@@ -570,12 +556,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
        }
        }
    }
    }


    private void setFirstElementRoundness(float firstElementRoundness) {
        if (mFirstElementRoundness != firstElementRoundness) {
            mFirstElementRoundness = firstElementRoundness;
        }
    }

    private void updateIconClipAmount(ExpandableNotificationRow row) {
    private void updateIconClipAmount(ExpandableNotificationRow row) {
        float maxTop = row.getTranslationY();
        float maxTop = row.getTranslationY();
        if (getClipTopAmount() != 0) {
        if (getClipTopAmount() != 0) {
@@ -1011,6 +991,18 @@ public class NotificationShelf extends ActivatableNotificationView implements
        expandableView.requestRoundnessReset(LegacySourceType.OnScroll);
        expandableView.requestRoundnessReset(LegacySourceType.OnScroll);
    }
    }


    @Override
    public void dump(PrintWriter pwOriginal, String[] args) {
        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
        super.dump(pw, args);
        if (DUMP_VERBOSE) {
            DumpUtilsKt.withIncreasedIndent(pw, () -> {
                pw.println("mActualWidth: " + mActualWidth);
                pw.println("mStatusBarHeight: " + mStatusBarHeight);
            });
        }
    }

    public class ShelfState extends ExpandableViewState {
    public class ShelfState extends ExpandableViewState {
        private boolean hasItemsInStableShelf;
        private boolean hasItemsInStableShelf;
        private ExpandableView firstViewInShelf;
        private ExpandableView firstViewInShelf;
+19 −5
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.IndentingPrintWriter;
import android.util.MathUtils;
import android.util.MathUtils;
import android.view.Choreographer;
import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.MotionEvent;
@@ -43,7 +44,9 @@ import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.util.DumpUtilsKt;


import java.io.PrintWriter;
import java.util.HashSet;
import java.util.HashSet;
import java.util.Set;
import java.util.Set;


@@ -651,11 +654,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        mBackgroundNormal.setRadius(topRadius, bottomRadius);
        mBackgroundNormal.setRadius(topRadius, bottomRadius);
    }
    }


    @Override
    protected void setBackgroundTop(int backgroundTop) {
        mBackgroundNormal.setBackgroundTop(backgroundTop);
    }

    protected abstract View getContentView();
    protected abstract View getContentView();


    public int calculateBgColor() {
    public int calculateBgColor() {
@@ -819,6 +817,22 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        mOnDetachResetRoundness.add(sourceType);
        mOnDetachResetRoundness.add(sourceType);
    }
    }


    @Override
    public void dump(PrintWriter pwOriginal, String[] args) {
        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
        super.dump(pw, args);
        if (DUMP_VERBOSE) {
            DumpUtilsKt.withIncreasedIndent(pw, () -> {
                pw.println("mBackgroundNormal: " + mBackgroundNormal);
                if (mBackgroundNormal != null) {
                    DumpUtilsKt.withIncreasedIndent(pw, () -> {
                        mBackgroundNormal.dump(pw, args);
                    });
                }
            });
        }
    }

    public interface OnActivatedListener {
    public interface OnActivatedListener {
        void onActivated(ActivatableNotificationView view);
        void onActivated(ActivatableNotificationView view);
        void onActivationReset(ActivatableNotificationView view);
        void onActivationReset(ActivatableNotificationView view);
+20 −10
Original line number Original line Diff line number Diff line
@@ -24,12 +24,16 @@ import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.IndentingPrintWriter;
import android.view.View;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.ViewOutlineProvider;


import com.android.systemui.R;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.RoundableState;
import com.android.systemui.statusbar.notification.RoundableState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.util.DumpUtilsKt;

import java.io.PrintWriter;


/**
/**
 * Like {@link ExpandableView}, but setting an outline for the height and clipping.
 * Like {@link ExpandableView}, but setting an outline for the height and clipping.
@@ -43,7 +47,6 @@ public abstract class ExpandableOutlineView extends ExpandableView {
    private float mOutlineAlpha = -1f;
    private float mOutlineAlpha = -1f;
    private boolean mAlwaysRoundBothCorners;
    private boolean mAlwaysRoundBothCorners;
    private Path mTmpPath = new Path();
    private Path mTmpPath = new Path();
    private int mBackgroundTop;


    /**
    /**
     * {@code false} if the children views of the {@link ExpandableOutlineView} are translated when
     * {@code false} if the children views of the {@link ExpandableOutlineView} are translated when
@@ -59,7 +62,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
                // Only when translating just the contents, does the outline need to be shifted.
                // Only when translating just the contents, does the outline need to be shifted.
                int translation = !mDismissUsingRowTranslationX ? (int) getTranslation() : 0;
                int translation = !mDismissUsingRowTranslationX ? (int) getTranslation() : 0;
                int left = Math.max(translation, 0);
                int left = Math.max(translation, 0);
                int top = mClipTopAmount + mBackgroundTop;
                int top = mClipTopAmount;
                int right = getWidth() + Math.min(translation, 0);
                int right = getWidth() + Math.min(translation, 0);
                int bottom = Math.max(getActualHeight() - mClipBottomAmount, top);
                int bottom = Math.max(getActualHeight() - mClipBottomAmount, top);
                outline.setRect(left, top, right, bottom);
                outline.setRect(left, top, right, bottom);
@@ -92,7 +95,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
                    ? (int) getTranslation() : 0;
                    ? (int) getTranslation() : 0;
            int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f);
            int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f);
            left = Math.max(translation, 0) - halfExtraWidth;
            left = Math.max(translation, 0) - halfExtraWidth;
            top = mClipTopAmount + mBackgroundTop;
            top = mClipTopAmount;
            right = getWidth() + halfExtraWidth + Math.min(translation, 0);
            right = getWidth() + halfExtraWidth + Math.min(translation, 0);
            // If the top is rounded we want the bottom to be at most at the top roundness, in order
            // If the top is rounded we want the bottom to be at most at the top roundness, in order
            // to avoid the shadow changing when scrolling up.
            // to avoid the shadow changing when scrolling up.
@@ -228,13 +231,6 @@ public abstract class ExpandableOutlineView extends ExpandableView {
        super.applyRoundnessAndInvalidate();
        super.applyRoundnessAndInvalidate();
    }
    }


    protected void setBackgroundTop(int backgroundTop) {
        if (mBackgroundTop != backgroundTop) {
            mBackgroundTop = backgroundTop;
            invalidateOutline();
        }
    }

    public void onDensityOrFontScaleChanged() {
    public void onDensityOrFontScaleChanged() {
        initDimens();
        initDimens();
        applyRoundnessAndInvalidate();
        applyRoundnessAndInvalidate();
@@ -350,4 +346,18 @@ public abstract class ExpandableOutlineView extends ExpandableView {
    public Path getCustomClipPath(View child) {
    public Path getCustomClipPath(View child) {
        return null;
        return null;
    }
    }

    @Override
    public void dump(PrintWriter pwOriginal, String[] args) {
        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
        super.dump(pw, args);
        DumpUtilsKt.withIncreasedIndent(pw, () -> {
            pw.println("Roundness: " + getRoundableState().debugString());
            if (DUMP_VERBOSE) {
                pw.println("mCustomOutline: " + mCustomOutline + " mOutlineRect: " + mOutlineRect);
                pw.println("mOutlineAlpha: " + mOutlineAlpha);
                pw.println("mAlwaysRoundBothCorners: " + mAlwaysRoundBothCorners);
            }
        });
    }
}
}
+10 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,8 @@ import java.util.List;
 */
 */
public abstract class ExpandableView extends FrameLayout implements Dumpable, Roundable {
public abstract class ExpandableView extends FrameLayout implements Dumpable, Roundable {
    private static final String TAG = "ExpandableView";
    private static final String TAG = "ExpandableView";
    /** whether the dump() for this class should include verbose details */
    protected static final boolean DUMP_VERBOSE = false;


    private RoundableState mRoundableState = null;
    private RoundableState mRoundableState = null;
    protected OnHeightChangedListener mOnHeightChangedListener;
    protected OnHeightChangedListener mOnHeightChangedListener;
@@ -825,6 +827,14 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro
                viewState.dump(pw, args);
                viewState.dump(pw, args);
                pw.println();
                pw.println();
            }
            }
            if (DUMP_VERBOSE) {
                pw.println("mClipTopAmount: " + mClipTopAmount);
                pw.println("mClipBottomAmount " + mClipBottomAmount);
                pw.println("mClipToActualHeight: " + mClipToActualHeight);
                pw.println("mExtraWidthForClipping: " + mExtraWidthForClipping);
                pw.println("mMinimumHeightForClipping: " + mMinimumHeightForClipping);
                pw.println("getClipBounds(): " + getClipBounds());
            }
        });
        });
    }
    }


+19 −10
Original line number Original line Diff line number Diff line
@@ -28,12 +28,16 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.View;


import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.R;


import java.io.PrintWriter;
import java.util.Arrays;

/**
/**
 * A view that can be used for both the dimmed and normal background of an notification.
 * A view that can be used for both the dimmed and normal background of an notification.
 */
 */
public class NotificationBackgroundView extends View {
public class NotificationBackgroundView extends View implements Dumpable {


    private final boolean mDontModifyCorners;
    private final boolean mDontModifyCorners;
    private Drawable mBackground;
    private Drawable mBackground;
@@ -42,7 +46,6 @@ public class NotificationBackgroundView extends View {
    private int mTintColor;
    private int mTintColor;
    private final float[] mCornerRadii = new float[8];
    private final float[] mCornerRadii = new float[8];
    private boolean mBottomIsRounded;
    private boolean mBottomIsRounded;
    private int mBackgroundTop;
    private boolean mBottomAmountClips = true;
    private boolean mBottomAmountClips = true;
    private int mActualHeight = -1;
    private int mActualHeight = -1;
    private int mActualWidth = -1;
    private int mActualWidth = -1;
@@ -60,8 +63,7 @@ public class NotificationBackgroundView extends View {


    @Override
    @Override
    protected void onDraw(Canvas canvas) {
    protected void onDraw(Canvas canvas) {
        if (mClipTopAmount + mClipBottomAmount < getActualHeight() - mBackgroundTop
        if (mClipTopAmount + mClipBottomAmount < getActualHeight() || mExpandAnimationRunning) {
                || mExpandAnimationRunning) {
            canvas.save();
            canvas.save();
            if (!mExpandAnimationRunning) {
            if (!mExpandAnimationRunning) {
                canvas.clipRect(0, mClipTopAmount, getWidth(),
                canvas.clipRect(0, mClipTopAmount, getWidth(),
@@ -74,7 +76,7 @@ public class NotificationBackgroundView extends View {


    private void draw(Canvas canvas, Drawable drawable) {
    private void draw(Canvas canvas, Drawable drawable) {
        if (drawable != null) {
        if (drawable != null) {
            int top = mBackgroundTop;
            int top = 0;
            int bottom = getActualHeight();
            int bottom = getActualHeight();
            if (mBottomIsRounded
            if (mBottomIsRounded
                    && mBottomAmountClips
                    && mBottomAmountClips
@@ -261,11 +263,6 @@ public class NotificationBackgroundView extends View {
        }
        }
    }
    }


    public void setBackgroundTop(int backgroundTop) {
        mBackgroundTop = backgroundTop;
        invalidate();
    }

    /** Set the current expand animation size. */
    /** Set the current expand animation size. */
    public void setExpandAnimationSize(int width, int height) {
    public void setExpandAnimationSize(int width, int height) {
        mExpandAnimationHeight = height;
        mExpandAnimationHeight = height;
@@ -291,4 +288,16 @@ public class NotificationBackgroundView extends View {
    public void setPressedAllowed(boolean allowed) {
    public void setPressedAllowed(boolean allowed) {
        mIsPressedAllowed = allowed;
        mIsPressedAllowed = allowed;
    }
    }

    @Override
    public void dump(PrintWriter pw, String[] args) {
        pw.println("mDontModifyCorners: " + mDontModifyCorners);
        pw.println("mClipTopAmount: " + mClipTopAmount);
        pw.println("mClipBottomAmount: " + mClipBottomAmount);
        pw.println("mCornerRadii: " + Arrays.toString(mCornerRadii));
        pw.println("mBottomIsRounded: " + mBottomIsRounded);
        pw.println("mBottomAmountClips: " + mBottomAmountClips);
        pw.println("mActualWidth: " + mActualWidth);
        pw.println("mActualHeight: " + mActualHeight);
    }
}
}