Merge "Update clock burn-in so it doesn't clash with udpfs" into sc-qpr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d58d6bfd38
@@ -16,7 +16,7 @@
|
||||
|
||||
<resources>
|
||||
<!-- Minimum margin between clock and top of screen or ambient indication -->
|
||||
<dimen name="keyguard_clock_top_margin">76dp</dimen>
|
||||
<dimen name="keyguard_clock_top_margin">38dp</dimen>
|
||||
|
||||
<!-- Large clock maximum font size (dp is intentional, to prevent any further scaling) -->
|
||||
<dimen name="large_clock_text_size">200dp</dimen>
|
||||
|
||||
@@ -743,9 +743,7 @@
|
||||
<!-- The margin between the status view and the notifications on Keyguard.-->
|
||||
<dimen name="keyguard_status_view_bottom_margin">20dp</dimen>
|
||||
<!-- Minimum margin between clock and status bar -->
|
||||
<dimen name="keyguard_clock_top_margin">36dp</dimen>
|
||||
<!-- The margin between top of clock and bottom of lock icon. -->
|
||||
<dimen name="keyguard_clock_lock_margin">16dp</dimen>
|
||||
<dimen name="keyguard_clock_top_margin">18dp</dimen>
|
||||
<!-- The amount to shift the clocks during a small/large transition -->
|
||||
<dimen name="keyguard_clock_switch_y_shift">10dp</dimen>
|
||||
<!-- When large clock is showing, offset the smartspace by this amount -->
|
||||
@@ -1149,9 +1147,9 @@
|
||||
<dimen name="default_burn_in_prevention_offset">15dp</dimen>
|
||||
|
||||
<!-- The maximum offset for the under-display fingerprint sensor (UDFPS) icon in either
|
||||
direction that elements aer moved to prevent burn-in on AOD-->
|
||||
<dimen name="udfps_burn_in_offset_x">2dp</dimen>
|
||||
<dimen name="udfps_burn_in_offset_y">8dp</dimen>
|
||||
direction that elements are moved to prevent burn-in on AOD-->
|
||||
<dimen name="udfps_burn_in_offset_x">7px</dimen>
|
||||
<dimen name="udfps_burn_in_offset_y">28px</dimen>
|
||||
|
||||
<dimen name="corner_size">8dp</dimen>
|
||||
<dimen name="top_padding">0dp</dimen>
|
||||
|
||||
@@ -70,13 +70,16 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
* Clock for both small and large sizes
|
||||
*/
|
||||
private AnimatableClockController mClockViewController;
|
||||
private FrameLayout mClockFrame;
|
||||
private FrameLayout mClockFrame; // top aligned clock
|
||||
private AnimatableClockController mLargeClockViewController;
|
||||
private FrameLayout mLargeClockFrame;
|
||||
private FrameLayout mLargeClockFrame; // centered clock
|
||||
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final KeyguardBypassController mBypassController;
|
||||
|
||||
private int mLargeClockTopMargin = 0;
|
||||
private int mKeyguardClockTopMargin = 0;
|
||||
|
||||
/**
|
||||
* Listener for changes to the color palette.
|
||||
*
|
||||
@@ -175,6 +178,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
}
|
||||
mColorExtractor.addOnColorsChangedListener(mColorsListener);
|
||||
mView.updateColors(getGradientColors());
|
||||
mKeyguardClockTopMargin =
|
||||
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
|
||||
|
||||
if (mOnlyClock) {
|
||||
View ksa = mView.findViewById(R.id.keyguard_status_area);
|
||||
@@ -249,6 +254,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
*/
|
||||
public void onDensityOrFontScaleChanged() {
|
||||
mView.onDensityOrFontScaleChanged();
|
||||
mKeyguardClockTopMargin =
|
||||
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
|
||||
|
||||
updateClockLayout();
|
||||
}
|
||||
@@ -257,9 +264,12 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
if (mSmartspaceController.isEnabled()) {
|
||||
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT,
|
||||
MATCH_PARENT);
|
||||
lp.topMargin = getContext().getResources().getDimensionPixelSize(
|
||||
mLargeClockTopMargin = getContext().getResources().getDimensionPixelSize(
|
||||
R.dimen.keyguard_large_clock_top_margin);
|
||||
lp.topMargin = mLargeClockTopMargin;
|
||||
mLargeClockFrame.setLayoutParams(lp);
|
||||
} else {
|
||||
mLargeClockTopMargin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,6 +379,28 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get y-bottom position of the currently visible clock on the keyguard.
|
||||
* We can't directly getBottom() because clock changes positions in AOD for burn-in
|
||||
*/
|
||||
int getClockBottom(int statusBarHeaderHeight) {
|
||||
if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
|
||||
View clock = mLargeClockFrame.findViewById(
|
||||
com.android.systemui.R.id.animatable_clock_view_large);
|
||||
int frameHeight = mLargeClockFrame.getHeight();
|
||||
int clockHeight = clock.getHeight();
|
||||
return frameHeight / 2 + clockHeight / 2;
|
||||
} else {
|
||||
return mClockFrame.findViewById(
|
||||
com.android.systemui.R.id.animatable_clock_view).getHeight()
|
||||
+ statusBarHeaderHeight + mKeyguardClockTopMargin;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isClockTopAligned() {
|
||||
return mLargeClockFrame.getVisibility() != View.VISIBLE;
|
||||
}
|
||||
|
||||
private void updateAodIcons() {
|
||||
NotificationIconContainer nic = (NotificationIconContainer)
|
||||
mView.findViewById(
|
||||
|
||||
@@ -184,6 +184,20 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
return mView.getHeight() - mKeyguardClockSwitchController.getNotificationIconAreaHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get y-bottom position of the currently visible clock.
|
||||
*/
|
||||
public int getClockBottom(int statusBarHeaderHeight) {
|
||||
return mKeyguardClockSwitchController.getClockBottom(statusBarHeaderHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the currently displayed clock is top aligned (as opposed to center aligned)
|
||||
*/
|
||||
public boolean isClockTopAligned() {
|
||||
return mKeyguardClockSwitchController.isClockTopAligned();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the view accessibility importance mode.
|
||||
*/
|
||||
|
||||
@@ -83,8 +83,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
private int mNotificationStackHeight;
|
||||
|
||||
/**
|
||||
* Minimum top margin to avoid overlap with status bar, lock icon, or multi-user switcher
|
||||
* avatar.
|
||||
* Minimum top margin to avoid overlap with status bar, or multi-user switcher avatar.
|
||||
*/
|
||||
private int mMinTopMargin;
|
||||
|
||||
@@ -149,6 +148,25 @@ public class KeyguardClockPositionAlgorithm {
|
||||
|
||||
private boolean mIsSplitShade;
|
||||
|
||||
/**
|
||||
* Top location of the udfps icon. This includes the worst case (highest) burn-in
|
||||
* offset that would make the top physically highest on the screen.
|
||||
*
|
||||
* Set to -1 if udfps is not enrolled on the device.
|
||||
*/
|
||||
private float mUdfpsTop;
|
||||
|
||||
/**
|
||||
* Bottom y-position of the currently visible clock
|
||||
*/
|
||||
private float mClockBottom;
|
||||
|
||||
/**
|
||||
* If true, try to keep clock aligned to the top of the display. Else, assume the clock
|
||||
* is center aligned.
|
||||
*/
|
||||
private boolean mIsClockTopAligned;
|
||||
|
||||
/**
|
||||
* Refreshes the dimension values.
|
||||
*/
|
||||
@@ -157,7 +175,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
R.dimen.keyguard_status_view_bottom_margin);
|
||||
|
||||
mContainerTopPadding =
|
||||
res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) / 2;
|
||||
res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
|
||||
mBurnInPreventionOffsetX = res.getDimensionPixelSize(
|
||||
R.dimen.burn_in_prevention_offset_x);
|
||||
mBurnInPreventionOffsetY = res.getDimensionPixelSize(
|
||||
@@ -174,7 +192,8 @@ public class KeyguardClockPositionAlgorithm {
|
||||
int keyguardStatusHeight, int userSwitchHeight, int userSwitchPreferredY,
|
||||
boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
|
||||
float overStrechAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
|
||||
float qsExpansion, int cutoutTopInset, boolean isSplitShade) {
|
||||
float qsExpansion, int cutoutTopInset, boolean isSplitShade, float udfpsTop,
|
||||
float clockBottom, boolean isClockTopAligned) {
|
||||
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
|
||||
userSwitchHeight);
|
||||
mMaxShadeBottom = maxShadeBottom;
|
||||
@@ -193,6 +212,9 @@ public class KeyguardClockPositionAlgorithm {
|
||||
mQsExpansion = qsExpansion;
|
||||
mCutoutTopInset = cutoutTopInset;
|
||||
mIsSplitShade = isSplitShade;
|
||||
mUdfpsTop = udfpsTop;
|
||||
mClockBottom = clockBottom;
|
||||
mIsClockTopAligned = isClockTopAligned;
|
||||
}
|
||||
|
||||
public void run(Result result) {
|
||||
@@ -247,8 +269,34 @@ public class KeyguardClockPositionAlgorithm {
|
||||
if (clockY - mBurnInPreventionOffsetYLargeClock < mCutoutTopInset) {
|
||||
shift = mCutoutTopInset - (clockY - mBurnInPreventionOffsetYLargeClock);
|
||||
}
|
||||
float clockYDark = clockY + burnInPreventionOffsetY() + shift;
|
||||
|
||||
int burnInPreventionOffsetY = mBurnInPreventionOffsetYLargeClock; // requested offset
|
||||
final boolean hasUdfps = mUdfpsTop > -1;
|
||||
if (hasUdfps && !mIsClockTopAligned) {
|
||||
// ensure clock doesn't overlap with the udfps icon
|
||||
if (mUdfpsTop < mClockBottom) {
|
||||
// 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 (mBurnInPreventionOffsetYLargeClock < burnInPreventionOffsetY) {
|
||||
burnInPreventionOffsetY = mBurnInPreventionOffsetYLargeClock;
|
||||
}
|
||||
shift = -burnInPreventionOffsetY;
|
||||
} else {
|
||||
float upperSpace = clockY - mCutoutTopInset;
|
||||
float lowerSpace = mUdfpsTop - mClockBottom;
|
||||
// center the burn-in offset within the upper + lower space
|
||||
burnInPreventionOffsetY = (int) (lowerSpace + upperSpace) / 2;
|
||||
if (mBurnInPreventionOffsetYLargeClock < burnInPreventionOffsetY) {
|
||||
burnInPreventionOffsetY = mBurnInPreventionOffsetYLargeClock;
|
||||
}
|
||||
shift = (lowerSpace - upperSpace) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
float clockYDark = clockY
|
||||
+ burnInPreventionOffsetY(burnInPreventionOffsetY)
|
||||
+ shift;
|
||||
return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount);
|
||||
}
|
||||
|
||||
@@ -280,9 +328,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
|
||||
}
|
||||
|
||||
private float burnInPreventionOffsetY() {
|
||||
int offset = mBurnInPreventionOffsetYLargeClock;
|
||||
|
||||
private float burnInPreventionOffsetY(int offset) {
|
||||
return getBurnInOffset(offset * 2, false /* xAxis */) - offset;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.biometrics.BiometricSourceType;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
@@ -621,6 +622,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
*/
|
||||
private float mKeyguardOnlyContentAlpha = 1.0f;
|
||||
|
||||
private float mUdfpsMaxYBurnInOffset;
|
||||
|
||||
/**
|
||||
* Are we currently in gesture navigation
|
||||
*/
|
||||
@@ -957,6 +960,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mResources);
|
||||
mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
|
||||
R.dimen.notification_side_paddings);
|
||||
mUdfpsMaxYBurnInOffset = mResources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
|
||||
}
|
||||
|
||||
private void updateViewControllers(KeyguardStatusView keyguardStatusView,
|
||||
@@ -1301,7 +1305,16 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
float darkamount =
|
||||
mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
|
||||
? 1.0f : mInterpolatedDarkAmount;
|
||||
mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
|
||||
|
||||
float udfpsAodTopLocation = -1f;
|
||||
if (mUpdateMonitor.isUdfpsEnrolled() && mAuthController.getUdfpsProps().size() > 0) {
|
||||
FingerprintSensorPropertiesInternal props = mAuthController.getUdfpsProps().get(0);
|
||||
udfpsAodTopLocation = props.sensorLocationY - props.sensorRadius
|
||||
- mUdfpsMaxYBurnInOffset;
|
||||
}
|
||||
|
||||
mClockPositionAlgorithm.setup(
|
||||
mStatusBarHeaderHeightKeyguard,
|
||||
totalHeight - bottomPadding,
|
||||
mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
|
||||
expandedFraction,
|
||||
@@ -1313,7 +1326,10 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
bypassEnabled, getUnlockedStackScrollerPadding(),
|
||||
computeQsExpansionFraction(),
|
||||
mDisplayTopInset,
|
||||
mShouldUseSplitNotificationShade);
|
||||
mShouldUseSplitNotificationShade,
|
||||
udfpsAodTopLocation,
|
||||
mKeyguardStatusViewController.getClockBottom(mStatusBarHeaderHeightKeyguard),
|
||||
mKeyguardStatusViewController.isClockTopAligned());
|
||||
mClockPositionAlgorithm.run(mClockPositionResult);
|
||||
boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
|
||||
boolean animateClock = animate || mAnimateNextPositionUpdate;
|
||||
|
||||
@@ -119,6 +119,7 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
when(mNotificationIcons.getLayoutParams()).thenReturn(
|
||||
mock(RelativeLayout.LayoutParams.class));
|
||||
when(mView.getContext()).thenReturn(getContext());
|
||||
when(mView.getResources()).thenReturn(mResources);
|
||||
|
||||
when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView);
|
||||
when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView);
|
||||
@@ -127,7 +128,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
when(mLargeClockView.getContext()).thenReturn(getContext());
|
||||
|
||||
when(mView.isAttachedToWindow()).thenReturn(true);
|
||||
when(mResources.getString(anyInt())).thenReturn("h:mm");
|
||||
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
|
||||
mController = new KeyguardClockSwitchController(
|
||||
mView,
|
||||
|
||||
@@ -16,24 +16,37 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.AdditionalAnswers.returnsFirstArg;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.doze.util.BurnInHelperKt;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.MockitoSession;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
|
||||
|
||||
private static final int SCREEN_HEIGHT = 2000;
|
||||
private static final int EMPTY_MARGIN = 0;
|
||||
private static final int EMPTY_HEIGHT = 0;
|
||||
private static final float ZERO_DRAG = 0.f;
|
||||
private static final float OPAQUE = 1.f;
|
||||
@@ -41,10 +54,15 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
|
||||
private static final boolean HAS_CUSTOM_CLOCK = false;
|
||||
private static final boolean HAS_VISIBLE_NOTIFS = false;
|
||||
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
|
||||
private KeyguardClockPositionAlgorithm mClockPositionAlgorithm;
|
||||
private KeyguardClockPositionAlgorithm.Result mClockPosition;
|
||||
private MockitoSession mStaticMockSession;
|
||||
private int mNotificationStackHeight;
|
||||
private float mPanelExpansion;
|
||||
private int mKeyguardStatusBarHeaderHeight;
|
||||
private int mKeyguardStatusHeight;
|
||||
private float mDark;
|
||||
private boolean mHasCustomClock;
|
||||
@@ -52,16 +70,32 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
|
||||
private float mQsExpansion;
|
||||
private int mCutoutTopInset = 0; // in pixels
|
||||
private boolean mIsSplitShade = false;
|
||||
private float mUdfpsTop = -1;
|
||||
private float mClockBottom = SCREEN_HEIGHT / 2;
|
||||
private boolean mClockTopAligned;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mStaticMockSession = mockitoSession()
|
||||
.mockStatic(BurnInHelperKt.class)
|
||||
.startMocking();
|
||||
|
||||
mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm();
|
||||
when(mResources.getDimensionPixelSize(anyInt())).thenReturn(0);
|
||||
mClockPositionAlgorithm.loadDimens(mResources);
|
||||
|
||||
mClockPosition = new KeyguardClockPositionAlgorithm.Result();
|
||||
|
||||
mHasCustomClock = HAS_CUSTOM_CLOCK;
|
||||
mHasVisibleNotifs = HAS_VISIBLE_NOTIFS;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mStaticMockSession.finishMocking();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clockPositionTopOfScreenOnAOD() {
|
||||
// GIVEN on AOD and both stack scroll and clock have 0 height
|
||||
@@ -338,6 +372,155 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
|
||||
assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clockPositionMinimizesBurnInMovementToAvoidUdfpsOnAOD() {
|
||||
// GIVEN a center aligned clock
|
||||
mClockTopAligned = false;
|
||||
|
||||
// GIVEN the clock + udfps are 100px apart
|
||||
mClockBottom = SCREEN_HEIGHT - 500;
|
||||
mUdfpsTop = SCREEN_HEIGHT - 400;
|
||||
|
||||
// GIVEN it's AOD and the burn-in y value is 200
|
||||
givenAOD();
|
||||
givenMaxBurnInOffset(200);
|
||||
|
||||
// WHEN the clock position algorithm is run with the highest burn in offset
|
||||
givenHighestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN the worst-case clock Y position is shifted only by 100 (not the full 200),
|
||||
// so that it's at the same location as mUdfpsTop
|
||||
assertThat(mClockPosition.clockY).isEqualTo(100);
|
||||
|
||||
// WHEN the clock position algorithm is run with the lowest burn in offset
|
||||
givenLowestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN lowest case starts at mCutoutTopInset
|
||||
assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clockPositionShiftsToAvoidUdfpsOnAOD_usesSpaceAboveClock() {
|
||||
// GIVEN a center aligned clock
|
||||
mClockTopAligned = false;
|
||||
|
||||
// GIVEN there's space at the top of the screen on LS (that's available to be used for
|
||||
// burn-in on AOD)
|
||||
mKeyguardStatusBarHeaderHeight = 150;
|
||||
|
||||
// GIVEN the bottom of the clock is beyond the top of UDFPS
|
||||
mClockBottom = SCREEN_HEIGHT - 300;
|
||||
mUdfpsTop = SCREEN_HEIGHT - 400;
|
||||
|
||||
// GIVEN it's AOD and the burn-in y value is 200
|
||||
givenAOD();
|
||||
givenMaxBurnInOffset(200);
|
||||
|
||||
// WHEN the clock position algorithm is run with the highest burn in offset
|
||||
givenHighestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN the algo should shift the clock up and use the area above the clock for
|
||||
// burn-in since the burn in offset > space above clock
|
||||
assertThat(mClockPosition.clockY).isEqualTo(mKeyguardStatusBarHeaderHeight);
|
||||
|
||||
// WHEN the clock position algorithm is run with the lowest burn in offset
|
||||
givenLowestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN lowest case starts at mCutoutTopInset (0 in this case)
|
||||
assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clockPositionShiftsToAvoidUdfpsOnAOD_usesMaxBurnInOffset() {
|
||||
// GIVEN a center aligned clock
|
||||
mClockTopAligned = false;
|
||||
|
||||
// GIVEN there's 200px space at the top of the screen on LS (that's available to be used for
|
||||
// burn-in on AOD) but 50px are taken up by the cutout
|
||||
mKeyguardStatusBarHeaderHeight = 200;
|
||||
mCutoutTopInset = 50;
|
||||
|
||||
// GIVEN the bottom of the clock is beyond the top of UDFPS
|
||||
mClockBottom = SCREEN_HEIGHT - 300;
|
||||
mUdfpsTop = SCREEN_HEIGHT - 400;
|
||||
|
||||
// GIVEN it's AOD and the burn-in y value is only 25px (less than space above clock)
|
||||
givenAOD();
|
||||
int maxYBurnInOffset = 25;
|
||||
givenMaxBurnInOffset(maxYBurnInOffset);
|
||||
|
||||
// WHEN the clock position algorithm is run with the highest burn in offset
|
||||
givenHighestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN the algo should shift the clock up and use the area above the clock for
|
||||
// burn-in
|
||||
assertThat(mClockPosition.clockY).isEqualTo(mKeyguardStatusBarHeaderHeight);
|
||||
|
||||
// WHEN the clock position algorithm is run with the lowest burn in offset
|
||||
givenLowestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN lowest case starts above mKeyguardStatusBarHeaderHeight
|
||||
assertThat(mClockPosition.clockY).isEqualTo(
|
||||
mKeyguardStatusBarHeaderHeight - 2 * maxYBurnInOffset);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clockPositionShiftsToMaximizeUdfpsBurnInMovement() {
|
||||
// GIVEN a center aligned clock
|
||||
mClockTopAligned = false;
|
||||
|
||||
// GIVEN there's 200px space at the top of the screen on LS (that's available to be used for
|
||||
// burn-in on AOD) but 50px are taken up by the cutout
|
||||
mKeyguardStatusBarHeaderHeight = 200;
|
||||
mCutoutTopInset = 50;
|
||||
int upperSpaceAvailable = mKeyguardStatusBarHeaderHeight - mCutoutTopInset;
|
||||
|
||||
// GIVEN the bottom of the clock and the top of UDFPS are 100px apart
|
||||
mClockBottom = SCREEN_HEIGHT - 500;
|
||||
mUdfpsTop = SCREEN_HEIGHT - 400;
|
||||
float lowerSpaceAvailable = mUdfpsTop - mClockBottom;
|
||||
|
||||
// GIVEN it's AOD and the burn-in y value is 200
|
||||
givenAOD();
|
||||
givenMaxBurnInOffset(200);
|
||||
|
||||
// WHEN the clock position algorithm is run with the highest burn in offset
|
||||
givenHighestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN the algo should shift the clock up and use both the area above
|
||||
// the clock and below the clock (vertically centered in its allowed area)
|
||||
assertThat(mClockPosition.clockY).isEqualTo(
|
||||
(int) (mCutoutTopInset + upperSpaceAvailable + lowerSpaceAvailable));
|
||||
|
||||
// WHEN the clock position algorithm is run with the lowest burn in offset
|
||||
givenLowestBurnInOffset();
|
||||
positionClock();
|
||||
|
||||
// THEN lowest case starts at mCutoutTopInset
|
||||
assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset);
|
||||
}
|
||||
|
||||
private void givenHighestBurnInOffset() {
|
||||
when(BurnInHelperKt.getBurnInOffset(anyInt(), anyBoolean())).then(returnsFirstArg());
|
||||
}
|
||||
|
||||
private void givenLowestBurnInOffset() {
|
||||
when(BurnInHelperKt.getBurnInOffset(anyInt(), anyBoolean())).thenReturn(0);
|
||||
}
|
||||
|
||||
private void givenMaxBurnInOffset(int offset) {
|
||||
when(mResources.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y_large_clock))
|
||||
.thenReturn(offset);
|
||||
mClockPositionAlgorithm.loadDimens(mResources);
|
||||
}
|
||||
|
||||
private void givenAOD() {
|
||||
mPanelExpansion = 1.f;
|
||||
mDark = 1.f;
|
||||
@@ -348,13 +531,33 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
|
||||
mDark = 0.f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup and run the clock position algorithm.
|
||||
*
|
||||
* mClockPosition.clockY will contain the top y-coordinate for the clock position
|
||||
*/
|
||||
private void positionClock() {
|
||||
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
|
||||
mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight,
|
||||
0 /* userSwitchHeight */, 0 /* userSwitchPreferredY */,
|
||||
mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
|
||||
0 /* unlockedStackScrollerPadding */, mQsExpansion,
|
||||
mCutoutTopInset, mIsSplitShade);
|
||||
mClockPositionAlgorithm.setup(
|
||||
mKeyguardStatusBarHeaderHeight,
|
||||
SCREEN_HEIGHT,
|
||||
mNotificationStackHeight,
|
||||
mPanelExpansion,
|
||||
SCREEN_HEIGHT,
|
||||
mKeyguardStatusHeight,
|
||||
0 /* userSwitchHeight */,
|
||||
0 /* userSwitchPreferredY */,
|
||||
mHasCustomClock,
|
||||
mHasVisibleNotifs,
|
||||
mDark,
|
||||
ZERO_DRAG,
|
||||
false /* bypassEnabled */,
|
||||
0 /* unlockedStackScrollerPadding */,
|
||||
mQsExpansion,
|
||||
mCutoutTopInset,
|
||||
mIsSplitShade,
|
||||
mUdfpsTop,
|
||||
mClockBottom,
|
||||
mClockTopAligned);
|
||||
mClockPositionAlgorithm.run(mClockPosition);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user