[Fold to AOD animation] part 3: do not collapse notification shade and delay doze display mode

Fixes a few issues with fold to AOD animation:

1) Sometimes when folding a foldable device and showing AOD
we see the underlying app (launcher/wallpaper)
for 1-2 seconds. It happens because the system
sends 'hide system dialogs' broadcast when starting
dreaming which collapses and hides the notification shade.
We need the notification shade in expanded state to show
the scrims and AOD UI. Added ignoring of collapsing when
fold to AOD animation is hapenning.

2) When folding from unlocked state the animation was
playing with reduced FPS (the display was going into
doze mode). Added delay for going into doze mode
when animation is about to happen.

Bug: 202844967
Test: fold/unfold when locked/unlocked
Test: power button screen off from locked/unlocked states
Change-Id: I2af5e4965ef7db234a1931ca442640c96000ec56
This commit is contained in:
Nick Chameyev
2022-01-18 18:05:44 +00:00
parent 165edbb17d
commit d63ed921ea
9 changed files with 57 additions and 11 deletions

View File

@@ -163,16 +163,12 @@ public class DozeScreenState implements DozeMachine.Part {
// Delay screen state transitions even longer while animations are running.
boolean shouldDelayTransitionEnteringDoze = newState == DOZE_AOD
&& mParameters.shouldControlScreenOff() && !turningOn;
&& mParameters.shouldDelayDisplayDozeTransition() && !turningOn;
// Delay screen state transition longer if UDFPS is actively authenticating a fp
boolean shouldDelayTransitionForUDFPS = newState == DOZE_AOD
&& mUdfpsController != null && mUdfpsController.isFingerDown();
if (shouldDelayTransitionEnteringDoze || shouldDelayTransitionForUDFPS) {
mWakeLock.setAcquired(true);
}
if (!messagePending) {
if (DEBUG) {
Log.d(TAG, "Display state changed to " + screenState + " delayed by "
@@ -180,6 +176,18 @@ public class DozeScreenState implements DozeMachine.Part {
}
if (shouldDelayTransitionEnteringDoze) {
if (justInitialized) {
// If we are delaying transitioning to doze and the display was not
// turned on we set it to 'on' first to make sure that the animation
// is visible before eventually moving it to doze state.
// The display might be off at this point for example on foldable devices
// when we switch displays and go to doze at the same time.
applyScreenState(Display.STATE_ON);
// Restore pending screen state as it gets cleared by 'applyScreenState'
mPendingScreenState = screenState;
}
mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY);
} else if (shouldDelayTransitionForUDFPS) {
mDozeLog.traceDisplayStateDelayedByUdfps(mPendingScreenState);
@@ -190,6 +198,10 @@ public class DozeScreenState implements DozeMachine.Part {
} else if (DEBUG) {
Log.d(TAG, "Pending display state change to " + screenState);
}
if (shouldDelayTransitionEnteringDoze || shouldDelayTransitionForUDFPS) {
mWakeLock.setAcquired(true);
}
} else if (turningOff) {
mDozeHost.prepareForGentleSleep(() -> applyScreenState(screenState));
} else {

View File

@@ -355,7 +355,8 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context,
}
override fun onDraw(canvas: Canvas?) {
if (canvas == null || revealGradientWidth <= 0 || revealGradientHeight <= 0) {
if (canvas == null || revealGradientWidth <= 0 || revealGradientHeight <= 0
|| revealAmount == 0f) {
if (revealAmount < 1f) {
canvas?.drawColor(revealGradientEndColor)
}

View File

@@ -304,6 +304,14 @@ public class DozeParameters implements
return mScreenOffAnimationController.shouldAnimateDozingChange();
}
/**
* When this method returns true then moving display state to power save mode will be
* delayed for a few seconds. This might be useful to play animations without reducing FPS.
*/
public boolean shouldDelayDisplayDozeTransition() {
return mScreenOffAnimationController.shouldDelayDisplayDozeTransition();
}
/**
* Whether we're capable of controlling the screen off animation if we want to. This isn't
* possible if AOD isn't even enabled or if the flag is disabled.

View File

@@ -179,6 +179,14 @@ class ScreenOffAnimationController @Inject constructor(
fun shouldAnimateDozingChange(): Boolean =
animations.all { it.shouldAnimateDozingChange() }
/**
* Returns true when moving display state to power save mode should be
* delayed for a few seconds. This might be useful to play animations in full quality,
* without reducing FPS.
*/
fun shouldDelayDisplayDozeTransition(): Boolean =
animations.any { it.shouldDelayDisplayDozeTransition() }
/**
* Return true to animate large <-> small clock transition
*/
@@ -207,6 +215,7 @@ interface ScreenOffAnimation {
fun shouldHideScrimOnWakeUp(): Boolean = false
fun overrideNotificationsDozeAmount(): Boolean = false
fun shouldShowAodIconsWhenShade(): Boolean = false
fun shouldDelayDisplayDozeTransition(): Boolean = false
fun shouldAnimateAodIcons(): Boolean = true
fun shouldAnimateDozingChange(): Boolean = true
fun shouldAnimateClockChange(): Boolean = true

View File

@@ -123,7 +123,8 @@ public class ShadeControllerImpl implements ShadeController {
+ " canPanelBeCollapsed(): "
+ getNotificationPanelViewController().canPanelBeCollapsed());
if (getNotificationShadeWindowView() != null
&& getNotificationPanelViewController().canPanelBeCollapsed()) {
&& getNotificationPanelViewController().canPanelBeCollapsed()
&& (flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
// release focus immediately to kick off focus change transition
mNotificationShadeWindowController.setNotificationShadeFocusable(false);

View File

@@ -268,6 +268,7 @@ public class StatusBar extends CoreStartable implements
// Should match the values in PhoneWindowManager
public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
public static final String SYSTEM_DIALOG_REASON_DREAM = "dream";
static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
private static final String BANNER_ACTION_CANCEL =
@@ -2635,8 +2636,17 @@ public class StatusBar extends CoreStartable implements
if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
int flags = CommandQueue.FLAG_EXCLUDE_NONE;
String reason = intent.getStringExtra("reason");
if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
if (reason != null) {
if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
}
// Do not collapse notifications when starting dreaming if the notifications
// shade is used for the screen off animation. It might require expanded
// state for the scrims to be visible
if (reason.equals(SYSTEM_DIALOG_REASON_DREAM)
&& mScreenOffAnimationController.shouldExpandNotifications()) {
flags |= CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL;
}
}
mShadeController.animateCollapsePanels(flags);
}

View File

@@ -290,6 +290,9 @@ class UnlockedScreenOffAnimationController @Inject constructor(
return true
}
override fun shouldDelayDisplayDozeTransition(): Boolean =
dozeParameters.get().shouldControlUnlockedScreenOff()
fun addCallback(callback: Callback) {
callbacks.add(callback)
}

View File

@@ -136,6 +136,8 @@ constructor(
override fun shouldAnimateClockChange(): Boolean = !isAnimationPlaying()
override fun shouldDelayDisplayDozeTransition(): Boolean = shouldPlayAnimation()
/** Called when AOD status is changed */
override fun onAlwaysOnChanged(alwaysOn: Boolean) {
alwaysOnEnabled = alwaysOn

View File

@@ -192,7 +192,7 @@ public class DozeScreenStateTest extends SysuiTestCase {
public void test_holdsWakeLockWhenGoingToLowPowerDelayed() {
// Transition to low power mode will be delayed to let
// animations play at 60 fps.
when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
when(mDozeParameters.shouldDelayDisplayDozeTransition()).thenReturn(true);
mHandlerFake.setMode(QUEUEING);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -209,7 +209,7 @@ public class DozeScreenStateTest extends SysuiTestCase {
public void test_releasesWakeLock_abortingLowPowerDelayed() {
// Transition to low power mode will be delayed to let
// animations play at 60 fps.
when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
when(mDozeParameters.shouldDelayDisplayDozeTransition()).thenReturn(true);
mHandlerFake.setMode(QUEUEING);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);