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

Commit 49fa2fb7 authored by Lyn Han's avatar Lyn Han Committed by Android (Google) Code Review
Browse files

Merge "Fix one-icon shelf flicker on lockscreen swipe-up" into tm-dev

parents 55f43e04 1c88a2be
Loading
Loading
Loading
Loading
+27 −12
Original line number Original line Diff line number Diff line
@@ -326,9 +326,9 @@ public class NotificationShelf extends ActivatableNotificationView implements
                    || child.isPinned();
                    || child.isPinned();
            boolean isLastChild = child == lastChild;
            boolean isLastChild = child == lastChild;
            final float viewStart = child.getTranslationY();
            final float viewStart = child.getTranslationY();

            final float shelfClipStart = getTranslationY() - mPaddingBetweenElements;
            final float inShelfAmount = updateShelfTransformation(i, child, scrollingFast,
            final float inShelfAmount = getAmountInShelf(i, child, scrollingFast,
                    expandingAnimated, isLastChild);
                    expandingAnimated, isLastChild, shelfClipStart);


            // TODO(b/172289889) scale mPaddingBetweenElements with expansion amount
            // TODO(b/172289889) scale mPaddingBetweenElements with expansion amount
            if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) {
            if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) {
@@ -609,10 +609,18 @@ public class NotificationShelf extends ActivatableNotificationView implements
    }
    }


    /**
    /**
     * @return the amount how much this notification is in the shelf
     * @param i Index of the view in the host layout.
     * @param view The current ExpandableView.
     * @param scrollingFast Whether we are scrolling fast.
     * @param expandingAnimated Whether we are expanding a notification.
     * @param isLastChild Whether this is the last view.
     * @param shelfClipStart The point at which notifications start getting clipped by the shelf.
     * @return The amount how much this notification is in the shelf.
     *         0f is not in shelf. 1f is completely in shelf.
     */
     */
    private float updateShelfTransformation(int i, ExpandableView view, boolean scrollingFast,
    @VisibleForTesting
            boolean expandingAnimated, boolean isLastChild) {
    public float getAmountInShelf(int i, ExpandableView view, boolean scrollingFast,
            boolean expandingAnimated, boolean isLastChild, float shelfClipStart) {


        // Let's calculate how much the view is in the shelf
        // Let's calculate how much the view is in the shelf
        float viewStart = view.getTranslationY();
        float viewStart = view.getTranslationY();
@@ -635,29 +643,33 @@ public class NotificationShelf extends ActivatableNotificationView implements
        float viewEnd = viewStart + fullHeight;
        float viewEnd = viewStart + fullHeight;
        float fullTransitionAmount = 0.0f;
        float fullTransitionAmount = 0.0f;
        float iconTransitionAmount = 0.0f;
        float iconTransitionAmount = 0.0f;
        float shelfStart = getTranslationY() - mPaddingBetweenElements;

        // Don't animate shelf icons during shade expansion.
        if (mAmbientState.isExpansionChanging() && !mAmbientState.isOnKeyguard()) {
        if (mAmbientState.isExpansionChanging() && !mAmbientState.isOnKeyguard()) {
            // TODO(b/172289889) handle icon placement for notification that is clipped by the shelf
            // TODO(b/172289889) handle icon placement for notification that is clipped by the shelf
            if (mIndexOfFirstViewInShelf != -1 && i >= mIndexOfFirstViewInShelf) {
            if (mIndexOfFirstViewInShelf != -1 && i >= mIndexOfFirstViewInShelf) {
                fullTransitionAmount = 1f;
                fullTransitionAmount = 1f;
                iconTransitionAmount = 1f;
                iconTransitionAmount = 1f;
            }
            }
        } else if (viewEnd >= shelfStart

        } else if (viewEnd >= shelfClipStart
                && (!mAmbientState.isUnlockHintRunning() || view.isInShelf())
                && (!mAmbientState.isUnlockHintRunning() || view.isInShelf())
                && (mAmbientState.isShadeExpanded()
                && (mAmbientState.isShadeExpanded()
                || (!view.isPinned() && !view.isHeadsUpAnimatingAway()))) {
                || (!view.isPinned() && !view.isHeadsUpAnimatingAway()))) {


            if (viewStart < shelfStart) {
            if (viewStart < shelfClipStart && Math.abs(viewStart - shelfClipStart) > 0.001f) {
                float fullAmount = (shelfStart - viewStart) / fullHeight;
                // Partially clipped by shelf.
                float fullAmount = (shelfClipStart - viewStart) / fullHeight;
                fullAmount = Math.min(1.0f, fullAmount);
                fullAmount = Math.min(1.0f, fullAmount);
                fullTransitionAmount = 1.0f - fullAmount;
                fullTransitionAmount = 1.0f - fullAmount;
                if (isLastChild) {
                if (isLastChild) {
                    // Reduce icon transform distance to completely fade in shelf icon
                    // Reduce icon transform distance to completely fade in shelf icon
                    // by the time the notification icon fades out, and vice versa
                    // by the time the notification icon fades out, and vice versa
                    iconTransitionAmount = (shelfStart - viewStart)
                    iconTransitionAmount = (shelfClipStart - viewStart)
                            / (iconTransformStart - viewStart);
                            / (iconTransformStart - viewStart);
                } else {
                } else {
                    iconTransitionAmount = (shelfStart - iconTransformStart) / transformDistance;
                    iconTransitionAmount = (shelfClipStart - iconTransformStart)
                            / transformDistance;
                }
                }
                iconTransitionAmount = MathUtils.constrain(iconTransitionAmount, 0.0f, 1.0f);
                iconTransitionAmount = MathUtils.constrain(iconTransitionAmount, 0.0f, 1.0f);
                iconTransitionAmount = 1.0f - iconTransitionAmount;
                iconTransitionAmount = 1.0f - iconTransitionAmount;
@@ -772,6 +784,9 @@ public class NotificationShelf extends ActivatableNotificationView implements
    }
    }


    private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) {
    private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) {
        if (mShelfIcons == null) {
            return null;
        }
        return mShelfIcons.getIconState(icon);
        return mShelfIcons.getIconState(icon);
    }
    }


+110 −2
Original line number Original line Diff line number Diff line
@@ -5,8 +5,9 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.NotificationShelf
import junit.framework.Assert.assertFalse
import com.android.systemui.statusbar.StatusBarIconView
import junit.framework.Assert.assertTrue
import com.android.systemui.statusbar.notification.row.ExpandableView
import junit.framework.Assert.*
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
@@ -143,6 +144,113 @@ class NotificationShelfTest : SysuiTestCase() {
        assertFalse(isYBelowShelfInView)
        assertFalse(isYBelowShelfInView)
    }
    }


    @Test
    fun getAmountInShelf_lastViewBelowShelf_completelyInShelf() {
        val shelfClipStart = 0f
        val viewStart = 1f

        val expandableView = mock(ExpandableView::class.java)
        whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
        whenever(expandableView.translationY).thenReturn(viewStart)
        whenever(expandableView.actualHeight).thenReturn(20)

        whenever(expandableView.minHeight).thenReturn(20)
        whenever(expandableView.shelfTransformationTarget).thenReturn(null)  // use translationY
        whenever(expandableView.isInShelf).thenReturn(true)

        whenever(ambientState.isOnKeyguard).thenReturn(true)
        whenever(ambientState.isExpansionChanging).thenReturn(false)
        whenever(ambientState.isShadeExpanded).thenReturn(true)

        val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
                /* view= */ expandableView,
                /* scrollingFast= */ false,
                /* expandingAnimated= */ false,
                /* isLastChild= */ true,
                shelfClipStart)
        assertEquals(1f, amountInShelf)
    }

    @Test
    fun getAmountInShelf_lastViewAlmostBelowShelf_completelyInShelf() {
        val viewStart = 0f
        val shelfClipStart = 0.001f

        val expandableView = mock(ExpandableView::class.java)
        whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
        whenever(expandableView.translationY).thenReturn(viewStart)
        whenever(expandableView.actualHeight).thenReturn(20)

        whenever(expandableView.minHeight).thenReturn(20)
        whenever(expandableView.shelfTransformationTarget).thenReturn(null)  // use translationY
        whenever(expandableView.isInShelf).thenReturn(true)

        whenever(ambientState.isOnKeyguard).thenReturn(true)
        whenever(ambientState.isExpansionChanging).thenReturn(false)
        whenever(ambientState.isShadeExpanded).thenReturn(true)

        val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
                /* view= */ expandableView,
                /* scrollingFast= */ false,
                /* expandingAnimated= */ false,
                /* isLastChild= */ true,
                shelfClipStart)
        assertEquals(1f, amountInShelf)
    }

    @Test
    fun getAmountInShelf_lastViewHalfClippedByShelf_halfInShelf() {
        val viewStart = 0f
        val shelfClipStart = 10f

        val expandableView = mock(ExpandableView::class.java)
        whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
        whenever(expandableView.translationY).thenReturn(viewStart)
        whenever(expandableView.actualHeight).thenReturn(25)

        whenever(expandableView.minHeight).thenReturn(25)
        whenever(expandableView.shelfTransformationTarget).thenReturn(null)  // use translationY
        whenever(expandableView.isInShelf).thenReturn(true)

        whenever(ambientState.isOnKeyguard).thenReturn(true)
        whenever(ambientState.isExpansionChanging).thenReturn(false)
        whenever(ambientState.isShadeExpanded).thenReturn(true)

        val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
                /* view= */ expandableView,
                /* scrollingFast= */ false,
                /* expandingAnimated= */ false,
                /* isLastChild= */ true,
                shelfClipStart)
        assertEquals(0.5f, amountInShelf)
    }

    @Test
    fun getAmountInShelf_lastViewAboveShelf_notInShelf() {
        val viewStart = 0f
        val shelfClipStart = 15f

        val expandableView = mock(ExpandableView::class.java)
        whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
        whenever(expandableView.translationY).thenReturn(viewStart)
        whenever(expandableView.actualHeight).thenReturn(10)

        whenever(expandableView.minHeight).thenReturn(10)
        whenever(expandableView.shelfTransformationTarget).thenReturn(null)  // use translationY
        whenever(expandableView.isInShelf).thenReturn(false)

        whenever(ambientState.isExpansionChanging).thenReturn(false)
        whenever(ambientState.isOnKeyguard).thenReturn(true)

        val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
                /* view= */ expandableView,
                /* scrollingFast= */ false,
                /* expandingAnimated= */ false,
                /* isLastChild= */ true,
                shelfClipStart)
        assertEquals(0f, amountInShelf)
    }

    private fun setFractionToShade(fraction: Float) {
    private fun setFractionToShade(fraction: Float) {
        whenever(ambientState.fractionToShade).thenReturn(fraction)
        whenever(ambientState.fractionToShade).thenReturn(fraction)
    }
    }