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

This commit is contained in:
William Leshner
2022-02-24 22:16:52 +00:00
committed by Android (Google) Code Review
4 changed files with 44 additions and 11 deletions

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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