diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index f9841005e8f72..1630244468e58 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -43,12 +43,6 @@
android:visibility="invisible" />
-
-
+
+
{
- mKeyguardStatusViewAnimating = false;
+ mKeyguardStatusViewVisibilityAnimating = false;
mView.setVisibility(View.INVISIBLE);
};
private final Runnable mAnimateKeyguardStatusViewGoneEndRunnable = () -> {
- mKeyguardStatusViewAnimating = false;
+ mKeyguardStatusViewVisibilityAnimating = false;
mView.setVisibility(View.GONE);
};
private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
- mKeyguardStatusViewAnimating = false;
+ mKeyguardStatusViewVisibilityAnimating = false;
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 0fdaae82e2d00..5c8c9f22d5852 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -96,7 +96,9 @@ public class DozeUi implements DozeMachine.Part {
*/
private void updateAnimateScreenOff() {
if (mCanAnimateTransition) {
- final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing
+ final boolean controlScreenOff =
+ mDozeParameters.getAlwaysOn()
+ && (mKeyguardShowing || mDozeParameters.shouldControlUnlockedScreenOff())
&& !mHost.isPowerSaveActive();
mDozeParameters.setControlScreenOffAnimation(controlScreenOff);
mHost.setAnimateScreenOff(controlScreenOff);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index bf87ac46cff1c..e7326698e43ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -92,8 +92,10 @@ import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.dagger.KeyguardModule;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -147,7 +149,8 @@ import dagger.Lazy;
* directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
* thread of the keyguard.
*/
-public class KeyguardViewMediator extends SystemUI implements Dumpable {
+public class KeyguardViewMediator extends SystemUI implements Dumpable,
+ StatusBarStateController.StateListener {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
@@ -221,6 +224,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
private boolean mBootSendUserPresent;
private boolean mShuttingDown;
private boolean mDozing;
+ private boolean mAnimatingScreenOff;
private final FalsingCollector mFalsingCollector;
/** High level access to the power manager for WakeLocks */
@@ -707,6 +711,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
};
private DeviceConfigProxy mDeviceConfig;
+ private DozeParameters mDozeParameters;
/**
* Injected constructor. See {@link KeyguardModule}.
@@ -723,7 +728,9 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
TrustManager trustManager,
DeviceConfigProxy deviceConfig,
NavigationModeController navigationModeController,
- KeyguardDisplayManager keyguardDisplayManager) {
+ KeyguardDisplayManager keyguardDisplayManager,
+ DozeParameters dozeParameters,
+ StatusBarStateController statusBarStateController) {
super(context);
mFalsingCollector = falsingCollector;
mLockPatternUtils = lockPatternUtils;
@@ -749,6 +756,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
QuickStepContract.isGesturalMode(navigationModeController.addListener(mode -> {
mInGestureNavigationMode = QuickStepContract.isGesturalMode(mode);
}));
+ mDozeParameters = dozeParameters;
+ statusBarStateController.addCallback(this);
}
public void userActivity() {
@@ -929,6 +938,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
mDeviceInteractive = false;
mGoingToSleep = false;
mWakeAndUnlocking = false;
+ mAnimatingScreenOff = mDozeParameters.shouldControlUnlockedScreenOff();
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
@@ -1081,6 +1091,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
// TODO: Rename all screen off/on references to interactive/sleeping
synchronized (this) {
mDeviceInteractive = true;
+ mAnimatingScreenOff = false;
cancelDoKeyguardLaterLocked();
cancelDoKeyguardForChildProfilesLocked();
if (DEBUG) Log.d(TAG, "onStartedWakingUp, seq = " + mDelayedShowingSequence);
@@ -1294,6 +1305,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
return mHiding;
}
+ public boolean isAnimatingScreenOff() {
+ return mAnimatingScreenOff;
+ }
+
/**
* Handles SET_OCCLUDED message sent by setOccluded()
*/
@@ -2266,6 +2281,16 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
setShowingLocked(mShowing);
}
+ @Override
+ public void onDozeAmountChanged(float linear, float interpolated) {
+ // If we were animating the screen off, and we've completed the doze animation (doze amount
+ // is 1f), then show the activity lock screen.
+ if (mAnimatingScreenOff && mDozing && linear == 1f) {
+ mAnimatingScreenOff = false;
+ setShowingLocked(mShowing);
+ }
+ }
+
/**
* @param pulsing true when device temporarily wakes up to display an incoming notification.
*/
@@ -2296,7 +2321,14 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
mAodShowing = aodShowing;
if (notifyDefaultDisplayCallbacks) {
notifyDefaultDisplayCallbacks(showing);
- updateActivityLockScreenState(showing, aodShowing);
+
+ if (!showing || !mAnimatingScreenOff) {
+ // Update the activity lock screen state unless we're animating in the keyguard
+ // for a screen off animation. In that case, we want the activity to remain visible
+ // until the animation completes. setShowingLocked is called again when the
+ // animation ends, so the activity lock screen will be shown at that time.
+ updateActivityLockScreenState(showing, aodShowing);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 626abfcc85fde..76281d8c0f002 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -43,6 +43,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.DeviceConfigProxy;
@@ -82,7 +83,9 @@ public class KeyguardModule {
@UiBackground Executor uiBgExecutor,
DeviceConfigProxy deviceConfig,
NavigationModeController navigationModeController,
- KeyguardDisplayManager keyguardDisplayManager) {
+ KeyguardDisplayManager keyguardDisplayManager,
+ DozeParameters dozeParameters,
+ StatusBarStateController statusBarStateController) {
return new KeyguardViewMediator(
context,
falsingCollector,
@@ -97,7 +100,9 @@ public class KeyguardModule {
trustManager,
deviceConfig,
navigationModeController,
- keyguardDisplayManager
+ keyguardDisplayManager,
+ dozeParameters,
+ statusBarStateController
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 1326d920fe42d..e391250dc8fd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -96,6 +96,8 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
}
+ private var animatingScreenOff = false
+
private var collapsedEnoughToHide: Boolean = false
var pulsing: Boolean = false
@@ -232,9 +234,14 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
override fun onDozeAmountChanged(linear: Float, eased: Float) {
- if (updateDozeAmountIfBypass()) {
+ if (overrideDozeAmountIfBypass()) {
return
}
+
+ if (overrideDozeAmountIfAnimatingScreenOff(linear)) {
+ return
+ }
+
if (linear != 1.0f && linear != 0.0f &&
(mLinearDozeAmount == 0.0f || mLinearDozeAmount == 1.0f)) {
// Let's notify the scroller that an animation started
@@ -257,7 +264,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
override fun onStateChanged(newState: Int) {
- updateDozeAmountIfBypass()
+ overrideDozeAmountIfBypass()
if (bypassController.bypassEnabled &&
newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
(!statusBarStateController.isDozing || shouldAnimateVisibility())) {
@@ -265,6 +272,14 @@ class NotificationWakeUpCoordinator @Inject constructor(
setNotificationsVisible(visible = true, increaseSpeed = false, animate = false)
setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
}
+
+ // If we want to control the screen off animation, check whether we are going from SHADE to
+ // KEYGUARD.
+ if (dozeParameters.shouldControlUnlockedScreenOff()) {
+ animatingScreenOff =
+ state == StatusBarState.SHADE && newState == StatusBarState.KEYGUARD
+ }
+
this.state = newState
}
@@ -280,7 +295,11 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
}
- private fun updateDozeAmountIfBypass(): Boolean {
+ /**
+ * @return Whether the doze amount was overridden because bypass is enabled. If true, the
+ * original doze amount should be ignored.
+ */
+ private fun overrideDozeAmountIfBypass(): Boolean {
if (bypassController.bypassEnabled) {
var amount = 1.0f
if (statusBarStateController.state == StatusBarState.SHADE ||
@@ -293,6 +312,28 @@ class NotificationWakeUpCoordinator @Inject constructor(
return false
}
+ /**
+ * If we're playing the screen off animation, force the notification doze amount to be 1f (fully
+ * dozing). This is needed so that the notifications aren't briefly visible as the screen turns
+ * off and dozeAmount goes from 1f to 0f.
+ *
+ * @return Whether the doze amount was overridden because we are playing the screen off
+ * animation. If true, the original doze amount should be ignored.
+ */
+ private fun overrideDozeAmountIfAnimatingScreenOff(linearDozeAmount: Float): Boolean {
+ if (animatingScreenOff) {
+ if (linearDozeAmount == 1f) {
+ animatingScreenOff = false
+ return false
+ }
+
+ setDozeAmount(1f, 1f)
+ return true
+ }
+
+ return false
+ }
+
private fun startVisibilityAnimation(increaseSpeed: Boolean) {
if (mNotificationVisibleAmount == 0f || mNotificationVisibleAmount == 1f) {
mVisibilityInterpolator = if (mNotificationsVisible)
@@ -345,6 +386,8 @@ class NotificationWakeUpCoordinator @Inject constructor(
override fun onDozingChanged(isDozing: Boolean) {
if (isDozing) {
setNotificationsVisible(visible = false, animate = false, increaseSpeed = false)
+ } else {
+ animatingScreenOff = false
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 64951448a543f..8c2fa3349e4a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -194,6 +194,16 @@ public class DozeParameters implements TunerService.Tunable,
mPowerManager.setDozeAfterScreenOff(!controlScreenOffAnimation);
}
+ /**
+ * Whether we want to control the screen off animation when the device is unlocked. If we do,
+ * we'll animate in AOD before turning off the screen, rather than simply fading to black and
+ * then abruptly showing AOD.
+ */
+ public boolean shouldControlUnlockedScreenOff() {
+ return getAlwaysOn() && SystemProperties.getBoolean(
+ "persist.sysui.show_new_screen_on_transitions", false);
+ }
+
private boolean getBoolean(String propName, int resId) {
return SystemProperties.getBoolean(propName, mResources.getBoolean(resId));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 1dfd1f3ef69c2..57a64e440bf66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -196,13 +196,15 @@ public class KeyguardClockPositionAlgorithm {
}
public void run(Result result) {
- final int y = getClockY(mPanelExpansion);
+ final int y = getClockY(mPanelExpansion, mDarkAmount);
result.clockY = y;
+ result.clockYFullyDozing = getClockY(
+ 1.0f /* panelExpansion */, 1.0f /* darkAmount */);
result.clockAlpha = getClockAlpha(y);
result.stackScrollerPadding = mBypassEnabled ? mUnlockedStackScrollerPadding
: y + mKeyguardStatusHeight;
result.stackScrollerPaddingExpanded = mBypassEnabled ? mUnlockedStackScrollerPadding
- : getClockY(1.0f) + mKeyguardStatusHeight;
+ : getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
result.clockScale = interpolate(getBurnInScale(), 1.0f, 1.0f - mDarkAmount);
}
@@ -259,7 +261,7 @@ public class KeyguardClockPositionAlgorithm {
return (int) y;
}
- private int getClockY(float panelExpansion) {
+ private int getClockY(float panelExpansion, float darkAmount) {
// Dark: Align the bottom edge of the clock at about half of the screen:
float clockYDark = (mHasCustomClock ? getPreferredClockY() : getMaxClockY())
+ burnInPreventionOffsetY();
@@ -273,7 +275,7 @@ public class KeyguardClockPositionAlgorithm {
float clockY = MathUtils.lerp(clockYBouncer, clockYRegular, shadeExpansion);
clockYDark = MathUtils.lerp(clockYBouncer, clockYDark, shadeExpansion);
- float darkAmount = mBypassEnabled && !mHasCustomClock ? 1.0f : mDarkAmount;
+ darkAmount = mBypassEnabled && !mHasCustomClock ? 1.0f : darkAmount;
if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
// This will keep the clock at the top but out of the cutout area
@@ -295,7 +297,7 @@ public class KeyguardClockPositionAlgorithm {
* @return Alpha from 0 to 1.
*/
private float getClockAlpha(int y) {
- float alphaKeyguard = Math.max(0, y / Math.max(1f, getClockY(1f)));
+ float alphaKeyguard = Math.max(0, y / Math.max(1f, getClockY(1f, mDarkAmount)));
alphaKeyguard *= (1f - mQsExpansion);
alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
@@ -327,6 +329,11 @@ public class KeyguardClockPositionAlgorithm {
*/
public int clockY;
+ /**
+ * The y translation of the clock when we're fully dozing.
+ */
+ public int clockYFullyDozing;
+
/**
* The alpha value of the clock.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 3e0978435e28a..2254ead99c849 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3617,6 +3617,16 @@ public class NotificationPanelViewController extends PanelViewController {
int oldState = mBarState;
boolean keyguardShowing = statusBarState == KEYGUARD;
+ if (mDozeParameters.shouldControlUnlockedScreenOff() && isDozing() && keyguardShowing) {
+ // This means we're doing the screen off animation - position the keyguard status
+ // view where it'll be on AOD, so we can animate it in.
+ mKeyguardStatusViewController.updatePosition(
+ mClockPositionResult.clockX,
+ mClockPositionResult.clockYFullyDozing,
+ mClockPositionResult.clockScale,
+ false);
+ }
+
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
statusBarState,
keyguardFadingAway,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 87a3ede629117..e07c3a536f682 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1384,7 +1384,7 @@ public class StatusBar extends SystemUI implements DemoMode,
* @param why the reason for the wake up
*/
public void wakeUpIfDozing(long time, View where, String why) {
- if (mDozing) {
+ if (mDozing && !mKeyguardViewMediator.isAnimatingScreenOff()) {
mPowerManager.wakeUp(
time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
mWakeUpComingFromTouch = true;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 4cfbe69f175f0..0074dbea11518 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -22,6 +22,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -50,6 +51,8 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
ConfigurationController mConfigurationController;
@Mock
NotificationIconAreaController mNotificationIconAreaController;
+ @Mock
+ DozeParameters mDozeParameters;
private KeyguardStatusViewController mController;
@@ -64,7 +67,8 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
mKeyguardStateController,
mKeyguardUpdateMonitor,
mConfigurationController,
- mNotificationIconAreaController);
+ mNotificationIconAreaController,
+ mDozeParameters);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 67d0295c82d30..00943bc53bfdd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -44,6 +44,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
@@ -73,6 +75,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock TrustManager mTrustManager;
private @Mock NavigationModeController mNavigationModeController;
private @Mock KeyguardDisplayManager mKeyguardDisplayManager;
+ private @Mock DozeParameters mDozeParameters;
+ private @Mock StatusBarStateController mStatusBarStateController;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -91,7 +95,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
() -> mStatusBarKeyguardViewManager,
mDismissCallbackRegistry, mUpdateMonitor, mDumpManager, mUiBgExecutor,
mPowerManager, mTrustManager, mDeviceConfig, mNavigationModeController,
- mKeyguardDisplayManager);
+ mKeyguardDisplayManager, mDozeParameters, mStatusBarStateController);
mViewMediator.start();
}