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

Commit 5c7cee2b authored by Michal Brzezinski's avatar Michal Brzezinski
Browse files

Fix heads-up notification being sometimes clipped when pulsing

The NSSL top padding is aligned with the clock top. The clock position moves throughout
time to avoid pixel burn-in and sometimes the position is above NSSL bounds, which makes the HUN be clipped.

The solution is to account for burn-in vertical shift when calculating NSSL position.
This means smartspace with clock will not always be aligned with HUN but it's agreed to be the best solution.

Also small renaming of burn-in related fields.

Test: KeyguardClockPositionAlgorithmTest.java
Test: Manually on-device with simulating biggest burn-in shift up
Fixes: 260084123
Change-Id: I211b15affef1c84d0b8524134b3af02894faf536
parent 8ec492a7
Loading
Loading
Loading
Loading
+26 −16
Original line number Diff line number Diff line
@@ -89,14 +89,19 @@ public class KeyguardClockPositionAlgorithm {
    private float mPanelExpansion;

    /**
     * Burn-in prevention x translation.
     * Max burn-in prevention x translation.
     */
    private int mBurnInPreventionOffsetX;
    private int mMaxBurnInPreventionOffsetX;

    /**
     * Burn-in prevention y translation for clock layouts.
     * Max burn-in prevention y translation for clock layouts.
     */
    private int mBurnInPreventionOffsetYClock;
    private int mMaxBurnInPreventionOffsetYClock;

    /**
     * Current burn-in prevention y translation.
     */
    private float mCurrentBurnInOffsetY;

    /**
     * Doze/AOD transition amount.
@@ -155,9 +160,9 @@ public class KeyguardClockPositionAlgorithm {

        mContainerTopPadding =
                res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
        mBurnInPreventionOffsetX = res.getDimensionPixelSize(
        mMaxBurnInPreventionOffsetX = res.getDimensionPixelSize(
                R.dimen.burn_in_prevention_offset_x);
        mBurnInPreventionOffsetYClock = res.getDimensionPixelSize(
        mMaxBurnInPreventionOffsetYClock = res.getDimensionPixelSize(
                R.dimen.burn_in_prevention_offset_y_clock);
    }

@@ -215,7 +220,10 @@ public class KeyguardClockPositionAlgorithm {
        if (mBypassEnabled) {
            return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
        } else if (mIsSplitShade) {
            return clockYPosition - mSplitShadeTopNotificationsMargin + mUserSwitchHeight;
            // mCurrentBurnInOffsetY is subtracted to make notifications not follow clock adjustment
            // for burn-in. It can make pulsing notification go too high and it will get clipped
            return clockYPosition - mSplitShadeTopNotificationsMargin + mUserSwitchHeight
                    - (int) mCurrentBurnInOffsetY;
        } else {
            return clockYPosition + mKeyguardStatusHeight;
        }
@@ -255,11 +263,11 @@ public class KeyguardClockPositionAlgorithm {

        // This will keep the clock at the top but out of the cutout area
        float shift = 0;
        if (clockY - mBurnInPreventionOffsetYClock < mCutoutTopInset) {
            shift = mCutoutTopInset - (clockY - mBurnInPreventionOffsetYClock);
        if (clockY - mMaxBurnInPreventionOffsetYClock < mCutoutTopInset) {
            shift = mCutoutTopInset - (clockY - mMaxBurnInPreventionOffsetYClock);
        }

        int burnInPreventionOffsetY = mBurnInPreventionOffsetYClock; // requested offset
        int burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock; // requested offset
        final boolean hasUdfps = mUdfpsTop > -1;
        if (hasUdfps && !mIsClockTopAligned) {
            // ensure clock doesn't overlap with the udfps icon
@@ -267,8 +275,8 @@ public class KeyguardClockPositionAlgorithm {
                // sometimes the clock textView extends beyond udfps, so let's just use the
                // space above the KeyguardStatusView/clock as our burn-in offset
                burnInPreventionOffsetY = (int) (clockY - mCutoutTopInset) / 2;
                if (mBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
                    burnInPreventionOffsetY = mBurnInPreventionOffsetYClock;
                if (mMaxBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
                    burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock;
                }
                shift = -burnInPreventionOffsetY;
            } else {
@@ -276,16 +284,18 @@ public class KeyguardClockPositionAlgorithm {
                float lowerSpace = mUdfpsTop - mClockBottom;
                // center the burn-in offset within the upper + lower space
                burnInPreventionOffsetY = (int) (lowerSpace + upperSpace) / 2;
                if (mBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
                    burnInPreventionOffsetY = mBurnInPreventionOffsetYClock;
                if (mMaxBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
                    burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock;
                }
                shift = (lowerSpace - upperSpace) / 2;
            }
        }

        float fullyDarkBurnInOffset = burnInPreventionOffsetY(burnInPreventionOffsetY);
        float clockYDark = clockY
                + burnInPreventionOffsetY(burnInPreventionOffsetY)
                + fullyDarkBurnInOffset
                + shift;
        mCurrentBurnInOffsetY = MathUtils.lerp(0, fullyDarkBurnInOffset, darkAmount);
        return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount);
    }

@@ -325,7 +335,7 @@ public class KeyguardClockPositionAlgorithm {
    }

    private float burnInPreventionOffsetX() {
        return getBurnInOffset(mBurnInPreventionOffsetX, true /* xAxis */);
        return getBurnInOffset(mMaxBurnInPreventionOffsetX, true /* xAxis */);
    }

    public static class Result {
+13 −0
Original line number Diff line number Diff line
@@ -263,6 +263,19 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
    }

    @Test
    public void notifPositionAlignedWithClockAndBurnInOffsetInSplitShadeMode() {
        setSplitShadeTopMargin(100); // this makes clock to be at 100
        givenAOD();
        mIsSplitShade = true;
        givenMaxBurnInOffset(100);
        givenHighestBurnInOffset(); // this makes clock to be at 200
        // WHEN the position algorithm is run
        positionClock();
        // THEN the notif padding adjusts for burn-in offset: clock position - burn-in offset
        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(100);
    }

    @Test
    public void clockPositionedDependingOnMarginInSplitShade() {
        setSplitShadeTopMargin(400);