Add support for seamless transion from/to AoD

Bug: 64155983
Test: runtest -x packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
Test: manual
Change-Id: I06e72cd5964944c79fb7bfda6881fc4a5a79ca7b
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 6f8bcff..a409fcb 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -63,7 +63,7 @@
                 new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
                 createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
                         handler, wakeLock, machine),
-                createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
+                createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
                 new DozeScreenState(wrappedService, handler),
                 createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler),
         });
@@ -89,8 +89,9 @@
     }
 
     private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
-            DozeMachine machine, Handler handler, AlarmManager alarmManager) {
-        return new DozeUi(context, alarmManager, machine, wakeLock, host, handler);
+            DozeMachine machine, Handler handler, AlarmManager alarmManager,
+            DozeParameters params) {
+        return new DozeUi(context, alarmManager, machine, wakeLock, host, handler, params);
     }
 
     public static DozeHost getHost(DozeService service) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 2f607ee..6a29299 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -38,6 +38,7 @@
     void extendPulse();
 
     void setAnimateWakeup(boolean animateWakeup);
+    void setAnimateScreenOff(boolean animateScreenOff);
 
     void onDoubleTap(float x, float y);
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 851b78c..b352ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -23,6 +23,7 @@
 import android.text.format.Formatter;
 import android.util.Log;
 
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.AlarmTimeout;
 import com.android.systemui.util.wakelock.WakeLock;
 
@@ -41,18 +42,22 @@
     private final WakeLock mWakeLock;
     private final DozeMachine mMachine;
     private final AlarmTimeout mTimeTicker;
+    private final boolean mCanAnimateWakeup;
 
     private long mLastTimeTickElapsed = 0;
 
     public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
-            WakeLock wakeLock, DozeHost host, Handler handler) {
+            WakeLock wakeLock, DozeHost host, Handler handler,
+            DozeParameters params) {
         mContext = context;
         mMachine = machine;
         mWakeLock = wakeLock;
         mHost = host;
         mHandler = handler;
+        mCanAnimateWakeup = !params.getDisplayNeedsBlanking();
 
         mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
+        mHost.setAnimateScreenOff(params.getCanControlScreenOffAnimation());
     }
 
     private void pulseWhileDozing(int reason) {
@@ -106,7 +111,7 @@
                 // Keep current state.
                 break;
             default:
-                mHost.setAnimateWakeup(false);
+                mHost.setAnimateWakeup(mCanAnimateWakeup);
                 break;
         }
     }
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 3f57c2f..50cbd69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -119,6 +119,28 @@
         return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
     }
 
+    /**
+     * Some screens need to be completely black before changing the display power mode,
+     * unexpected behavior might happen if this parameter isn't respected.
+     *
+     * @return true if screen needs to be completely black before a power transition.
+     */
+    public boolean getDisplayNeedsBlanking() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_displayBlanksAfterDoze);
+    }
+
+    /**
+     * Whether we can implement our own screen off animation or if we need
+     * to rely on DisplayPowerManager to dim the display.
+     *
+     * @return true if SystemUI can control the screen off animation.
+     */
+    public boolean getCanControlScreenOffAnimation() {
+        return !mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_dozeAfterScreenOff);
+    }
+
     private boolean getBoolean(String propName, int resId) {
         return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId));
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 0db98f3..c33cc50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -20,6 +20,7 @@
 import android.os.Trace;
 
 import com.android.systemui.statusbar.ScrimView;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 /**
  * Possible states of the ScrimController state machine.
@@ -38,12 +39,18 @@
 
         @Override
         public void prepare(ScrimState previousState) {
-            // DisplayPowerManager will blank the screen, we'll just
-            // set our scrim to black in this frame to avoid flickering and
-            // fade it out afterwards.
-            mBlankScreen = previousState == ScrimState.AOD;
+            mBlankScreen = false;
             if (previousState == ScrimState.AOD) {
-                updateScrimColor(mScrimInFront, 1, Color.BLACK);
+                mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+                if (mDisplayRequiresBlanking) {
+                    // DisplayPowerManager will blank the screen, we'll just
+                    // set our scrim to black in this frame to avoid flickering and
+                    // fade it out afterwards.
+                    mBlankScreen = true;
+                    updateScrimColor(mScrimInFront, 1, Color.BLACK);
+                }
+            } else {
+                mAnimationDuration = ScrimController.ANIMATION_DURATION;
             }
             mCurrentBehindAlpha = mScrimBehindAlphaKeyguard;
             mCurrentInFrontAlpha = 0;
@@ -78,7 +85,7 @@
     AOD {
         @Override
         public void prepare(ScrimState previousState) {
-            if (previousState == ScrimState.PULSING) {
+            if (previousState == ScrimState.PULSING && !mCanControlScreenOff) {
                 updateScrimColor(mScrimInFront, 1, Color.BLACK);
             }
             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
@@ -89,7 +96,7 @@
             mCurrentBehindTint = Color.BLACK;
             // DisplayPowerManager will blank the screen for us, we just need
             // to set our state.
-            mAnimateChange = false;
+            mAnimateChange = mCanControlScreenOff;
         }
     },
 
@@ -103,8 +110,10 @@
             mCurrentInFrontAlpha = 0;
             mCurrentInFrontTint = Color.BLACK;
             mCurrentBehindTint = Color.BLACK;
-            mBlankScreen = true;
-            updateScrimColor(mScrimInFront, 1, Color.BLACK);
+            mBlankScreen = mDisplayRequiresBlanking;
+            if (mDisplayRequiresBlanking) {
+                updateScrimColor(mScrimInFront, 1, Color.BLACK);
+            }
         }
     },
 
@@ -147,11 +156,15 @@
     ScrimView mScrimInFront;
     ScrimView mScrimBehind;
     DozeParameters mDozeParameters;
+    boolean mDisplayRequiresBlanking;
+    boolean mCanControlScreenOff;
 
     public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters) {
         mScrimInFront = scrimInFront;
         mScrimBehind = scrimBehind;
         mDozeParameters = dozeParameters;
+        mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
+        mCanControlScreenOff = dozeParameters.getCanControlScreenOffAnimation();
     }
 
     public void prepare(ScrimState previousState) {
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 c61b7e8..7b04f19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4407,7 +4407,8 @@
     private void updateDozingState() {
         Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
         Trace.beginSection("StatusBar#updateDozingState");
-        boolean animate = !mDozing && mDozeServiceHost.shouldAnimateWakeup();
+        boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup())
+                || (mDozing && mDozeServiceHost.shouldAnimateScreenOff());
         mNotificationPanel.setDozing(mDozing, animate);
         mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
         mDozeScrimController.setDozing(mDozing);
@@ -5175,6 +5176,7 @@
     private final class DozeServiceHost implements DozeHost {
         private final ArrayList<Callback> mCallbacks = new ArrayList<>();
         private boolean mAnimateWakeup;
+        private boolean mAnimateScreenOff;
         private boolean mIgnoreTouchWhilePulsing;
 
         @Override
@@ -5322,6 +5324,11 @@
         }
 
         @Override
+        public void setAnimateScreenOff(boolean animateScreenOff) {
+            mAnimateScreenOff = animateScreenOff;
+        }
+
+        @Override
         public void onDoubleTap(float screenX, float screenY) {
             if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
                 && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
@@ -5365,6 +5372,10 @@
         private boolean shouldAnimateWakeup() {
             return mAnimateWakeup;
         }
+
+        public boolean shouldAnimateScreenOff() {
+            return mAnimateScreenOff;
+        }
     }
 
     public boolean shouldIgnoreTouch() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index f78a718..236c348 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -40,7 +40,7 @@
 public class StackStateAnimator {
 
     public static final int ANIMATION_DURATION_STANDARD = 360;
-    public static final int ANIMATION_DURATION_WAKEUP = 200;
+    public static final int ANIMATION_DURATION_WAKEUP = 500;
     public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
     public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
     public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;