Screen off animation

SysUI can now control the screen off animation as long as
config_dozeAfterScreenOff is set to false.

The current implementation collapses the notification shade and moves
the clock whenever the use is on the lock screen, or will fade the
scrims and show the clock when the keyguard is occluded.

Display state change (on, doze, doze_suspended) is delayed to let the
animations occur at 60Hz.

Test: atest packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
Test: atest packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
Test: atest packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
Test: atest tests/src/com/android/systemui/statusbar/phone/DozeScrimControllerTest.java
Test: atest tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
Test: atest packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
Fixes: 73178121
Change-Id: Id5d964452f342d4e97bedf1084efa808604e602c
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 739d8d5..1fb4e13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -285,10 +285,11 @@
             // with too many things at this case, in order to not skip the initial frames.
             mScrimInFront.postOnAnimationDelayed(this::scheduleUpdate, 16);
             mAnimationDelay = StatusBar.FADE_KEYGUARD_START_DELAY;
-        } else if (!mDozeParameters.getAlwaysOn() && oldState == ScrimState.AOD) {
-            // Execute first frame immediately when display was completely off.
-            // Scheduling a frame isn't enough because the system may aggressively enter doze,
-            // delaying callbacks or never triggering them until the power button is pressed.
+        } else if (!mDozeParameters.getAlwaysOn() && oldState == ScrimState.AOD
+                || (mState == ScrimState.AOD && !mDozeParameters.getDisplayNeedsBlanking())) {
+            // Scheduling a frame isn't enough when:
+            //  • Leaving doze and we need to modify scrim color immediately
+            //  • ColorFade will not kick-in and scrim cannot wait for pre-draw.
             onPreDraw();
         } else {
             scheduleUpdate();