Merge "Update clock burn-in so it doesn't clash with udpfs" into sc-qpr1-dev

This commit is contained in:
TreeHugger Robot
2021-09-27 13:53:44 +00:00
committed by Android (Google) Code Review
8 changed files with 337 additions and 28 deletions

View File

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

View File

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

View File

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

View File

@@ -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.
*/

View File

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

View File

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

View File

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

View File

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