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

Commit c8dcc3e7 authored by William Leshner's avatar William Leshner Committed by Android (Google) Code Review
Browse files

Merge "Fix a bug with jittering dream overlay." into tm-dev

parents eebb589d 8692fcd0
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -695,4 +695,7 @@

    <!-- How often in milliseconds to jitter the dream overlay in order to avoid burn-in. -->
    <integer name="config_dreamOverlayBurnInProtectionUpdateIntervalMillis">500</integer>

    <!-- How long in milliseconds before full burn-in protection is achieved. -->
    <integer name="config_dreamOverlayMillisUntilFullJitter">240000</integer>
</resources>
+27 −6
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.dreams;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;

import android.os.Handler;
import android.util.MathUtils;
import android.view.View;
import android.view.ViewGroup;

@@ -56,9 +57,15 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
    // The interval in milliseconds between burn-in protection updates.
    private final long mBurnInProtectionUpdateInterval;

    // Amount of time in milliseconds to linear interpolate toward the final jitter offset. Once
    // this time is achieved, the normal jitter algorithm applies in full.
    private final long mMillisUntilFullJitter;

    // Main thread handler used to schedule periodic tasks (e.g. burn-in protection updates).
    private final Handler mHandler;

    private long mJitterStartTimeMillis;

    @Inject
    public DreamOverlayContainerViewController(
            DreamOverlayContainerView containerView,
@@ -68,7 +75,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
            @Main Handler handler,
            @Named(DreamOverlayModule.MAX_BURN_IN_OFFSET) int maxBurnInOffset,
            @Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
                    burnInProtectionUpdateInterval) {
                    burnInProtectionUpdateInterval,
            @Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter) {
        super(containerView);
        mDreamOverlayContentView = contentView;
        mStatusBarViewController = statusBarViewController;
@@ -86,6 +94,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
        mHandler = handler;
        mMaxBurnInOffset = maxBurnInOffset;
        mBurnInProtectionUpdateInterval = burnInProtectionUpdateInterval;
        mMillisUntilFullJitter = millisUntilFullJitter;
    }

    @Override
@@ -96,6 +105,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve

    @Override
    protected void onViewAttached() {
        mJitterStartTimeMillis = System.currentTimeMillis();
        mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval);
    }

@@ -114,13 +124,24 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
    }

    private void updateBurnInOffsets() {
        int burnInOffset = mMaxBurnInOffset;

        // Make sure the offset starts at zero, to avoid a big jump in the overlay when it first
        // appears.
        long millisSinceStart = System.currentTimeMillis() - mJitterStartTimeMillis;
        if (millisSinceStart < mMillisUntilFullJitter) {
            float lerpAmount = (float) millisSinceStart / (float) mMillisUntilFullJitter;
            burnInOffset = Math.round(MathUtils.lerp(0f, burnInOffset, lerpAmount));
        }

        // These translation values change slowly, and the set translation methods are idempotent,
        // so no translation occurs when the values don't change.
        mView.setTranslationX(getBurnInOffset(mMaxBurnInOffset * 2, true)
                - mMaxBurnInOffset);

        mView.setTranslationY(getBurnInOffset(mMaxBurnInOffset * 2, false)
                - mMaxBurnInOffset);
        int burnInOffsetX = getBurnInOffset(burnInOffset * 2, true)
                - burnInOffset;
        int burnInOffsetY = getBurnInOffset(burnInOffset * 2, false)
                - burnInOffset;
        mView.setTranslationX(burnInOffsetX);
        mView.setTranslationY(burnInOffsetY);

        mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval);
    }
+8 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ public abstract class DreamOverlayModule {
    public static final String MAX_BURN_IN_OFFSET = "max_burn_in_offset";
    public static final String BURN_IN_PROTECTION_UPDATE_INTERVAL =
            "burn_in_protection_update_interval";
    public static final String MILLIS_UNTIL_FULL_JITTER = "millis_until_full_jitter";

    /** */
    @Provides
@@ -106,6 +107,13 @@ public abstract class DreamOverlayModule {
                R.integer.config_dreamOverlayBurnInProtectionUpdateIntervalMillis);
    }

    /** */
    @Provides
    @Named(MILLIS_UNTIL_FULL_JITTER)
    static long providesMillisUntilFullJitter(@Main Resources resources) {
        return resources.getInteger(R.integer.config_dreamOverlayMillisUntilFullJitter);
    }

    @Provides
    @DreamOverlayComponent.DreamOverlayScope
    static LifecycleOwner providesLifecycleOwner(Lazy<LifecycleRegistry> lifecycleRegistryLazy) {
+6 −5
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.dreams;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -49,6 +48,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
    private static final int DREAM_OVERLAY_NOTIFICATIONS_DRAG_AREA_HEIGHT = 100;
    private static final int MAX_BURN_IN_OFFSET = 20;
    private static final long BURN_IN_PROTECTION_UPDATE_INTERVAL = 10;
    private static final long MILLIS_UNTIL_FULL_JITTER = 240 * 1000;

    @Mock
    Resources mResources;
@@ -100,7 +100,8 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
                mDreamOverlayStatusBarViewController,
                mHandler,
                MAX_BURN_IN_OFFSET,
                BURN_IN_PROTECTION_UPDATE_INTERVAL);
                BURN_IN_PROTECTION_UPDATE_INTERVAL,
                MILLIS_UNTIL_FULL_JITTER);
    }

    @Test
@@ -129,14 +130,14 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
    }

    @Test
    public void testBurnInProtectionUpdatesPeriodically() {
    public void testBurnInProtectionOffsetsStartAtZero() {
        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
        mController.onViewAttached();
        verify(mHandler).postDelayed(
                runnableCaptor.capture(), eq(BURN_IN_PROTECTION_UPDATE_INTERVAL));
        runnableCaptor.getValue().run();
        verify(mDreamOverlayContainerView).setTranslationX(anyFloat());
        verify(mDreamOverlayContainerView).setTranslationY(anyFloat());
        verify(mDreamOverlayContainerView).setTranslationX(0.f);
        verify(mDreamOverlayContainerView).setTranslationY(0.f);
    }

    @Test