Revert "Revert "Move DozeServiceHost out of StatusBar.""

This restores the refactoring of DozeServiceHost.

It was originally reverted because of strange behavior seen on the
lock screen that prevents the phone from being unlocked. Upon
review, I found that a call to StatusBar.updateDozingState() had been
erroneously omitted from StatusBar.onDozingChanged. Restoring this
call seems to make the observed problem go away.

Bug: 143484506
Test: atest SystemUITests
Change-Id: Ic024db5a3f2bdca3e877aa067f21cab6a5a45454
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
index 6674c12..9032c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
@@ -20,6 +20,7 @@
 import com.android.systemui.appops.AppOpsController;
 import com.android.systemui.appops.AppOpsControllerImpl;
 import com.android.systemui.classifier.FalsingManagerProxy;
+import com.android.systemui.doze.DozeHost;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.FalsingManager;
@@ -33,6 +34,7 @@
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -241,5 +243,10 @@
     /**
      */
     @Binds
-    public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl);
+    public abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
+
+    /**
+     */
+    @Binds
+    public abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 033171a..1e8e28f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -55,10 +55,10 @@
 @Singleton
 public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
 
-    private static final String TAG = "BiometricUnlockController";
+    private static final String TAG = "BiometricUnlockCtrl";
     private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
     private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
-    private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
+    private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
 
     @IntDef(prefix = { "MODE_" }, value = {
             MODE_NONE,
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 50d33a7..bc48235 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -24,7 +24,6 @@
 import android.provider.Settings;
 import android.util.MathUtils;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.MainResources;
 import com.android.systemui.doze.AlwaysOnDisplayPolicy;
@@ -188,12 +187,7 @@
             return;
         }
         mControlScreenOffAnimation = controlScreenOffAnimation;
-        getPowerManager().setDozeAfterScreenOff(!controlScreenOffAnimation);
-    }
-
-    @VisibleForTesting
-    protected PowerManager getPowerManager() {
-        return mPowerManager;
+        mPowerManager.setDozeAfterScreenOff(!controlScreenOffAnimation);
     }
 
     private boolean getBoolean(String propName, int resId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index fe3c04e..1ecc489 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -29,10 +29,12 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 
 import javax.inject.Inject;
+import javax.inject.Singleton;
 
 /**
  * Controller which handles all the doze animations of the scrims.
  */
+@Singleton
 public class DozeScrimController implements StateListener {
     private static final String TAG = "DozeScrimController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
new file mode 100644
index 0000000..2854355
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.doze.DozeEvent;
+import com.android.systemui.doze.DozeHost;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.doze.DozeReceiver;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+/**
+ * Implementation of DozeHost for SystemUI.
+ */
+@Singleton
+public final class DozeServiceHost implements DozeHost {
+    private static final String TAG = "DozeServiceHost";
+    private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+    private final DozeLog mDozeLog;
+    private final PowerManager mPowerManager;
+    private boolean mAnimateWakeup;
+    private boolean mAnimateScreenOff;
+    private boolean mIgnoreTouchWhilePulsing;
+    private Runnable mPendingScreenOffCallback;
+    @VisibleForTesting
+    boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean(
+            "persist.sysui.wake_performs_auth", true);
+    private boolean mDozingRequested;
+    private boolean mDozing;
+    private boolean mPulsing;
+    private WakefulnessLifecycle mWakefulnessLifecycle;
+    private final SysuiStatusBarStateController mStatusBarStateController;
+    private final DeviceProvisionedController mDeviceProvisionedController;
+    private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+    private final BatteryController mBatteryController;
+    private final ScrimController mScrimController;
+    private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
+    private BiometricUnlockController mBiometricUnlockController;
+    private final KeyguardViewMediator mKeyguardViewMediator;
+    private final AssistManager mAssistManager;
+    private final DozeScrimController mDozeScrimController;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final VisualStabilityManager mVisualStabilityManager;
+    private final PulseExpansionHandler mPulseExpansionHandler;
+    private final StatusBarWindowController mStatusBarWindowController;
+    private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
+    private NotificationIconAreaController mNotificationIconAreaController;
+    private StatusBarWindowViewController mStatusBarWindowViewController;
+    private StatusBarWindowView mStatusBarWindow;
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private NotificationPanelView mNotificationPanel;
+    private View mAmbientIndicationContainer;
+    private StatusBar mStatusBar;
+
+    @Inject
+    public DozeServiceHost(DozeLog dozeLog, PowerManager powerManager,
+            WakefulnessLifecycle wakefulnessLifecycle,
+            SysuiStatusBarStateController statusBarStateController,
+            DeviceProvisionedController deviceProvisionedController,
+            HeadsUpManagerPhone headsUpManagerPhone, BatteryController batteryController,
+            ScrimController scrimController,
+            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+            KeyguardViewMediator keyguardViewMediator,
+            AssistManager assistManager,
+            DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor,
+            VisualStabilityManager visualStabilityManager,
+            PulseExpansionHandler pulseExpansionHandler,
+            StatusBarWindowController statusBarWindowController,
+            NotificationWakeUpCoordinator notificationWakeUpCoordinator) {
+        super();
+        mDozeLog = dozeLog;
+        mPowerManager = powerManager;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
+        mStatusBarStateController = statusBarStateController;
+        mDeviceProvisionedController = deviceProvisionedController;
+        mHeadsUpManagerPhone = headsUpManagerPhone;
+        mBatteryController = batteryController;
+        mScrimController = scrimController;
+        mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+        mKeyguardViewMediator = keyguardViewMediator;
+        mAssistManager = assistManager;
+        mDozeScrimController = dozeScrimController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mVisualStabilityManager = visualStabilityManager;
+        mPulseExpansionHandler = pulseExpansionHandler;
+        mStatusBarWindowController = statusBarWindowController;
+        mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
+    }
+
+    // TODO: we should try to not pass status bar in here if we can avoid it.
+
+    /**
+     * Initialize instance with objects only available later during execution.
+     */
+    public void initialize(StatusBar statusBar,
+            NotificationIconAreaController notificationIconAreaController,
+            StatusBarWindowViewController statusBarWindowViewController,
+            StatusBarWindowView statusBarWindow,
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            NotificationPanelView notificationPanel, View ambientIndicationContainer) {
+        mStatusBar = statusBar;
+        mNotificationIconAreaController = notificationIconAreaController;
+        mStatusBarWindowViewController = statusBarWindowViewController;
+        mStatusBarWindow = statusBarWindow;
+        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+        mNotificationPanel = notificationPanel;
+        mAmbientIndicationContainer = ambientIndicationContainer;
+        mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
+    }
+
+    @Override
+    public String toString() {
+        return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
+    }
+
+    void firePowerSaveChanged(boolean active) {
+        for (Callback callback : mCallbacks) {
+            callback.onPowerSaveChanged(active);
+        }
+    }
+
+    void fireNotificationPulse(NotificationEntry entry) {
+        Runnable pulseSuppressedListener = () -> {
+            entry.setPulseSuppressed(true);
+            mNotificationIconAreaController.updateAodNotificationIcons();
+        };
+        for (Callback callback : mCallbacks) {
+            callback.onNotificationAlerted(pulseSuppressedListener);
+        }
+    }
+
+    boolean getDozingRequested() {
+        return mDozingRequested;
+    }
+
+    boolean isPulsing() {
+        return mPulsing;
+    }
+
+
+    @Override
+    public void addCallback(@NonNull Callback callback) {
+        mCallbacks.add(callback);
+    }
+
+    @Override
+    public void removeCallback(@NonNull Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    @Override
+    public void startDozing() {
+        if (!mDozingRequested) {
+            mDozingRequested = true;
+            mDozeLog.traceDozing(mDozing);
+            updateDozing();
+            mStatusBar.updateIsKeyguard();
+        }
+    }
+
+    void updateDozing() {
+        // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
+        boolean
+                dozing =
+                mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+                        || mBiometricUnlockController.getMode()
+                        == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+        // When in wake-and-unlock we may not have received a change to StatusBarState
+        // but we still should not be dozing, manually set to false.
+        if (mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
+            dozing = false;
+        }
+
+
+        mStatusBarStateController.setIsDozing(dozing);
+    }
+
+    @Override
+    public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
+        if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) {
+            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+                                 "com.android.systemui:LONG_PRESS");
+            mAssistManager.startAssist(new Bundle());
+            return;
+        }
+
+        if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
+            mScrimController.setWakeLockScreenSensorActive(true);
+        }
+
+        if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
+            mStatusBarWindowViewController.suppressWakeUpGesture(true);
+        }
+
+        boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
+                        && mWakeLockScreenPerformsAuth;
+        // Set the state to pulsing, so ScrimController will know what to do once we ask it to
+        // execute the transition. The pulse callback will then be invoked when the scrims
+        // are black, indicating that StatusBar is ready to present the rest of the UI.
+        mPulsing = true;
+        mDozeScrimController.pulse(new PulseCallback() {
+            @Override
+            public void onPulseStarted() {
+                callback.onPulseStarted();
+                mStatusBar.updateNotificationPanelTouchState();
+                setPulsing(true);
+            }
+
+            @Override
+            public void onPulseFinished() {
+                mPulsing = false;
+                callback.onPulseFinished();
+                mStatusBar.updateNotificationPanelTouchState();
+                mScrimController.setWakeLockScreenSensorActive(false);
+                if (mStatusBarWindow != null) {
+                    mStatusBarWindowViewController.suppressWakeUpGesture(false);
+                }
+                setPulsing(false);
+            }
+
+            private void setPulsing(boolean pulsing) {
+                mStatusBarStateController.setPulsing(pulsing);
+                mStatusBarKeyguardViewManager.setPulsing(pulsing);
+                mKeyguardViewMediator.setPulsing(pulsing);
+                mNotificationPanel.setPulsing(pulsing);
+                mVisualStabilityManager.setPulsing(pulsing);
+                mStatusBarWindowViewController.setPulsing(pulsing);
+                mIgnoreTouchWhilePulsing = false;
+                if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
+                    mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
+                }
+                mStatusBar.updateScrimController();
+                mPulseExpansionHandler.setPulsing(pulsing);
+                mNotificationWakeUpCoordinator.setPulsing(pulsing);
+            }
+        }, reason);
+        // DozeScrimController is in pulse state, now let's ask ScrimController to start
+        // pulsing and draw the black frame, if necessary.
+        mStatusBar.updateScrimController();
+    }
+
+    @Override
+    public void stopDozing() {
+        if (mDozingRequested) {
+            mDozingRequested = false;
+            mDozeLog.traceDozing(mDozing);
+            updateDozing();
+        }
+    }
+
+    @Override
+    public void onIgnoreTouchWhilePulsing(boolean ignore) {
+        if (ignore != mIgnoreTouchWhilePulsing) {
+            mDozeLog.tracePulseTouchDisabledByProx(ignore);
+        }
+        mIgnoreTouchWhilePulsing = ignore;
+        if (mDozing && ignore) {
+            mStatusBarWindowViewController.cancelCurrentTouch();
+        }
+    }
+
+    @Override
+    public void dozeTimeTick() {
+        mNotificationPanel.dozeTimeTick();
+        if (mAmbientIndicationContainer instanceof DozeReceiver) {
+            ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
+        }
+    }
+
+    @Override
+    public boolean isPowerSaveActive() {
+        return mBatteryController.isAodPowerSave();
+    }
+
+    @Override
+    public boolean isPulsingBlocked() {
+        return mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
+    }
+
+    @Override
+    public boolean isProvisioned() {
+        return mDeviceProvisionedController.isDeviceProvisioned()
+                && mDeviceProvisionedController.isCurrentUserSetup();
+    }
+
+    @Override
+    public boolean isBlockingDoze() {
+        if (mBiometricUnlockController.hasPendingAuthentication()) {
+            Log.i(StatusBar.TAG, "Blocking AOD because fingerprint has authenticated");
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void extendPulse(int reason) {
+        if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
+            mScrimController.setWakeLockScreenSensorActive(true);
+        }
+        if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) {
+            mHeadsUpManagerPhone.extendHeadsUp();
+        } else {
+            mDozeScrimController.extendPulse();
+        }
+    }
+
+    @Override
+    public void stopPulsing() {
+        if (mDozeScrimController.isPulsing()) {
+            mDozeScrimController.pulseOutNow();
+        }
+    }
+
+    @Override
+    public void setAnimateWakeup(boolean animateWakeup) {
+        if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
+                || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) {
+            // Too late to change the wakeup animation.
+            return;
+        }
+        mAnimateWakeup = animateWakeup;
+    }
+
+    @Override
+    public void setAnimateScreenOff(boolean animateScreenOff) {
+        mAnimateScreenOff = animateScreenOff;
+    }
+
+    @Override
+    public void onSlpiTap(float screenX, float screenY) {
+        if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
+                && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
+            int[] locationOnScreen = new int[2];
+            mAmbientIndicationContainer.getLocationOnScreen(locationOnScreen);
+            float viewX = screenX - locationOnScreen[0];
+            float viewY = screenY - locationOnScreen[1];
+            if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
+                    && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
+
+                // Dispatch a tap
+                long now = SystemClock.elapsedRealtime();
+                MotionEvent ev = MotionEvent.obtain(
+                        now, now, MotionEvent.ACTION_DOWN, screenX, screenY, 0);
+                mAmbientIndicationContainer.dispatchTouchEvent(ev);
+                ev.recycle();
+                ev = MotionEvent.obtain(
+                        now, now, MotionEvent.ACTION_UP, screenX, screenY, 0);
+                mAmbientIndicationContainer.dispatchTouchEvent(ev);
+                ev.recycle();
+            }
+        }
+    }
+
+    @Override
+    public void setDozeScreenBrightness(int value) {
+        mStatusBarWindowController.setDozeScreenBrightness(value);
+    }
+
+    @Override
+    public void setAodDimmingScrim(float scrimOpacity) {
+        mScrimController.setAodFrontScrimAlpha(scrimOpacity);
+    }
+
+
+
+    @Override
+    public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
+        if (mPendingScreenOffCallback != null) {
+            Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one.");
+        }
+        mPendingScreenOffCallback = onDisplayOffCallback;
+        mStatusBar.updateScrimController();
+    }
+
+    @Override
+    public void cancelGentleSleep() {
+        mPendingScreenOffCallback = null;
+        if (mScrimController.getState() == ScrimState.OFF) {
+            mStatusBar.updateScrimController();
+        }
+    }
+
+    /**
+     * When the dozing host is waiting for scrims to fade out to change the display state.
+     */
+    boolean hasPendingScreenOffCallback() {
+        return mPendingScreenOffCallback != null;
+    }
+
+    /**
+     * Executes an nullifies the pending display state callback.
+     *
+     * @see #hasPendingScreenOffCallback()
+     * @see #prepareForGentleSleep(Runnable)
+     */
+    void executePendingScreenOffCallback() {
+        if (mPendingScreenOffCallback == null) {
+            return;
+        }
+        mPendingScreenOffCallback.run();
+        mPendingScreenOffCallback = null;
+    }
+
+    boolean shouldAnimateWakeup() {
+        return mAnimateWakeup;
+    }
+
+    boolean shouldAnimateScreenOff() {
+        return mAnimateScreenOff;
+    }
+
+    public void setDozing(boolean dozing) {
+        mDozing = dozing;
+    }
+
+    boolean getIgnoreTouchWhilePulsing() {
+        return mIgnoreTouchWhilePulsing;
+    }
+}
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 6064fbe..35039a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -60,11 +60,13 @@
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
+import javax.inject.Singleton;
 
 /**
  * Controls both the scrim behind the notifications and in front of the notifications (when a
  * security method gets shown).
  */
+@Singleton
 public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener,
         Dumpable {
 
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 2e0fbfa..971843e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -50,7 +50,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -157,10 +156,8 @@
 import com.android.systemui.charging.WirelessChargingAnimation;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.doze.DozeEvent;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
-import com.android.systemui.doze.DozeReceiver;
 import com.android.systemui.fragments.ExtensionFragmentListener;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -347,7 +344,7 @@
     /**
      * The {@link StatusBarState} of the status bar.
      */
-    protected int mState;
+    protected int mState; // TODO: remove this. Just use StatusBarStateController
     protected boolean mBouncerShowing;
 
     private PhoneStatusBarPolicy mIconPolicy;
@@ -373,7 +370,7 @@
     protected StatusBarWindowController mStatusBarWindowController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @VisibleForTesting
-    DozeServiceHost mDozeServiceHost = new DozeServiceHost();
+    DozeServiceHost mDozeServiceHost;
     private boolean mWakeUpComingFromTouch;
     private PointF mWakeUpTouchLocation;
 
@@ -493,7 +490,6 @@
     private final UiOffloadThread mUiOffloadThread;
 
     protected boolean mDozing;
-    private boolean mDozingRequested;
 
     private final NotificationMediaManager mMediaManager;
     private final NotificationLockscreenUserManager mLockscreenUserManager;
@@ -612,7 +608,6 @@
     private ActivityLaunchAnimator mActivityLaunchAnimator;
     protected StatusBarNotificationPresenter mPresenter;
     private NotificationActivityStarter mNotificationActivityStarter;
-    private boolean mPulsing;
     private final BubbleController mBubbleController;
     private final BubbleController.BubbleExpandListener mBubbleExpandListener;
 
@@ -692,7 +687,10 @@
             DozeParameters dozeParameters,
             ScrimController scrimController,
             Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
-            Lazy<BiometricUnlockController> biometricUnlockControllerLazy) {
+            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+            DozeServiceHost dozeServiceHost,
+            PowerManager powerManager,
+            DozeScrimController dozeScrimController) {
         super(context);
         mFeatureFlags = featureFlags;
         mLightBarController = lightBarController;
@@ -749,9 +747,12 @@
         mStatusBarWindowController = statusBarWindowController;
         mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder;
         mNotifLog = notifLog;
+        mDozeServiceHost = dozeServiceHost;
+        mPowerManager = powerManager;
         mDozeParameters = dozeParameters;
         mScrimController = scrimController;
         mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
+        mDozeScrimController = dozeScrimController;
         mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
 
         mBubbleExpandListener =
@@ -804,7 +805,6 @@
         mAccessibilityManager = (AccessibilityManager)
                 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
 
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -904,6 +904,9 @@
         startKeyguard();
 
         mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
+        mDozeServiceHost.initialize(this, mNotificationIconAreaController,
+                mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager,
+                mNotificationPanel, mAmbientIndicationContainer);
         putComponent(DozeHost.class, mDozeServiceHost);
 
         mScreenPinningRequest = new ScreenPinningRequest(mContext);
@@ -1068,7 +1071,6 @@
 
         mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
                 mHeadsUpManager, mNotificationIconAreaController, mScrimController);
-        mDozeScrimController = new DozeScrimController(mDozeParameters, mDozeLog);
 
         BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop);
         mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
@@ -1729,7 +1731,7 @@
         if (isDozing() && isHeadsUp) {
             entry.setPulseSuppressed(false);
             mDozeServiceHost.fireNotificationPulse(entry);
-            if (mPulsing) {
+            if (mDozeServiceHost.isPulsing()) {
                 mDozeScrimController.cancelPendingPulseTimeout();
             }
         }
@@ -1761,7 +1763,7 @@
     }
 
     public boolean isPulsing() {
-        return mPulsing;
+        return mDozeServiceHost.isPulsing();
     }
 
     public boolean hideStatusBarIconsWhenExpanded() {
@@ -2824,7 +2826,7 @@
         if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
                 && mKeyguardStateController.canDismissLockScreen()
                 && !mStatusBarStateController.leaveOpenOnKeyguardHide()
-                && isPulsing()) {
+                && mDozeServiceHost.isPulsing()) {
             // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
             // TODO: Factor this transition out of BiometricUnlockController.
             mBiometricUnlockController.startWakeAndUnlock(
@@ -3155,7 +3157,7 @@
         return mState == StatusBarState.FULLSCREEN_USER_SWITCHER;
     }
 
-    private boolean updateIsKeyguard() {
+    boolean updateIsKeyguard() {
         boolean wakeAndUnlocking = mBiometricUnlockController.getMode()
                 == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
 
@@ -3163,8 +3165,8 @@
         // there's no surface we can show to the user. Note that the device goes fully interactive
         // late in the transition, so we also allow the device to start dozing once the screen has
         // turned off fully.
-        boolean keyguardForDozing = mDozingRequested &&
-                (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
+        boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
+                && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
         boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
                 || keyguardForDozing) && !wakeAndUnlocking;
         if (keyguardForDozing) {
@@ -3580,7 +3582,7 @@
     public void onStateChanged(int newState) {
         mState = newState;
         updateReportRejectedTouchVisibility();
-        updateDozing();
+        mDozeServiceHost.updateDozing();
         updateTheme();
         mNavigationBarController.touchAutoDim(mDisplayId);
         Trace.beginSection("StatusBar#updateKeyguardState");
@@ -3618,9 +3620,11 @@
     public void onDozingChanged(boolean isDozing) {
         Trace.beginSection("StatusBar#updateDozing");
         mDozing = isDozing;
+        mDozeServiceHost.setDozing(mDozing);
 
         // Collapse the notification panel if open
-        boolean dozingAnimated = mDozingRequested && mDozeParameters.shouldControlScreenOff();
+        boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
+                && mDozeParameters.shouldControlScreenOff();
         mNotificationPanel.resetViews(dozingAnimated);
 
         updateQsExpansionEnabled();
@@ -3628,26 +3632,12 @@
 
         mEntryManager.updateNotifications("onDozingChanged");
         updateDozingState();
+        mDozeServiceHost.updateDozing();
         updateScrimController();
         updateReportRejectedTouchVisibility();
         Trace.endSection();
     }
 
-    private void updateDozing() {
-        // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
-        boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
-                || mBiometricUnlockController.getMode()
-                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
-        // When in wake-and-unlock we may not have received a change to mState
-        // but we still should not be dozing, manually set to false.
-        if (mBiometricUnlockController.getMode() ==
-                BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
-            dozing = false;
-        }
-
-        mStatusBarStateController.setIsDozing(dozing);
-    }
-
     private void updateKeyguardState() {
         mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
                 mStatusBarKeyguardViewManager.isOccluded());
@@ -3872,10 +3862,11 @@
      * collapse the panel after we expanded it, and thus we would end up with a blank
      * Keyguard.
      */
-    private void updateNotificationPanelTouchState() {
+    void updateNotificationPanelTouchState() {
         boolean goingToSleepWithoutAnimation = isGoingToSleep()
                 && !mDozeParameters.shouldControlScreenOff();
-        boolean disabled = (!mDeviceInteractive && !mPulsing) || goingToSleepWithoutAnimation;
+        boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
+                || goingToSleepWithoutAnimation;
         mNotificationPanel.setTouchAndAnimationDisabled(disabled);
         mNotificationIconAreaController.setAnimationsEnabled(!disabled);
     }
@@ -4025,7 +4016,7 @@
     }
 
     public void notifyBiometricAuthModeChanged() {
-        updateDozing();
+        mDozeServiceHost.updateDozing();
         updateScrimController();
         mStatusBarWindowViewController.onBiometricAuthModeChanged(
                 mBiometricUnlockController.isWakeAndUnlock(),
@@ -4061,7 +4052,7 @@
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         } else if (mBrightnessMirrorVisible) {
             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
-        } else if (isPulsing()) {
+        } else if (mDozeServiceHost.isPulsing()) {
             mScrimController.transitionTo(ScrimState.PULSING,
                     mDozeScrimController.getScrimCallback());
         } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
@@ -4091,295 +4082,8 @@
         return mStatusBarKeyguardViewManager.isShowing();
     }
 
-    @VisibleForTesting
-    final class DozeServiceHost implements DozeHost {
-        private final ArrayList<Callback> mCallbacks = new ArrayList<>();
-        private boolean mAnimateWakeup;
-        private boolean mAnimateScreenOff;
-        private boolean mIgnoreTouchWhilePulsing;
-        private Runnable mPendingScreenOffCallback;
-        @VisibleForTesting
-        boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean(
-                "persist.sysui.wake_performs_auth", true);
-
-        @Override
-        public String toString() {
-            return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
-        }
-
-        public void firePowerSaveChanged(boolean active) {
-            for (Callback callback : mCallbacks) {
-                callback.onPowerSaveChanged(active);
-            }
-        }
-
-        public void fireNotificationPulse(NotificationEntry entry) {
-            Runnable pulseSupressedListener = () -> {
-                entry.setPulseSuppressed(true);
-                mNotificationIconAreaController.updateAodNotificationIcons();
-            };
-            for (Callback callback : mCallbacks) {
-                callback.onNotificationAlerted(pulseSupressedListener);
-            }
-        }
-
-        @Override
-        public void addCallback(@NonNull Callback callback) {
-            mCallbacks.add(callback);
-        }
-
-        @Override
-        public void removeCallback(@NonNull Callback callback) {
-            mCallbacks.remove(callback);
-        }
-
-        @Override
-        public void startDozing() {
-            if (!mDozingRequested) {
-                mDozingRequested = true;
-                mDozeLog.traceDozing(mDozing);
-                updateDozing();
-                updateIsKeyguard();
-            }
-        }
-
-        @Override
-        public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
-            if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) {
-                mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
-                        "com.android.systemui:LONG_PRESS");
-                startAssist(new Bundle());
-                return;
-            }
-
-            if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
-                mScrimController.setWakeLockScreenSensorActive(true);
-            }
-
-            if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
-                mStatusBarWindowViewController.suppressWakeUpGesture(true);
-            }
-
-            boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
-                            && mWakeLockScreenPerformsAuth;
-            // Set the state to pulsing, so ScrimController will know what to do once we ask it to
-            // execute the transition. The pulse callback will then be invoked when the scrims
-            // are black, indicating that StatusBar is ready to present the rest of the UI.
-            mPulsing = true;
-            mDozeScrimController.pulse(new PulseCallback() {
-                @Override
-                public void onPulseStarted() {
-                    callback.onPulseStarted();
-                    updateNotificationPanelTouchState();
-                    setPulsing(true);
-                }
-
-                @Override
-                public void onPulseFinished() {
-                    mPulsing = false;
-                    callback.onPulseFinished();
-                    updateNotificationPanelTouchState();
-                    mScrimController.setWakeLockScreenSensorActive(false);
-                    if (mStatusBarWindow != null) {
-                        mStatusBarWindowViewController.suppressWakeUpGesture(false);
-                    }
-                    setPulsing(false);
-                }
-
-                private void setPulsing(boolean pulsing) {
-                    mStatusBarStateController.setPulsing(pulsing);
-                    mStatusBarKeyguardViewManager.setPulsing(pulsing);
-                    mKeyguardViewMediator.setPulsing(pulsing);
-                    mNotificationPanel.setPulsing(pulsing);
-                    mVisualStabilityManager.setPulsing(pulsing);
-                    mStatusBarWindowViewController.setPulsing(pulsing);
-                    mIgnoreTouchWhilePulsing = false;
-                    if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
-                        mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
-                    }
-                    updateScrimController();
-                    mPulseExpansionHandler.setPulsing(pulsing);
-                    mWakeUpCoordinator.setPulsing(pulsing);
-                }
-            }, reason);
-            // DozeScrimController is in pulse state, now let's ask ScrimController to start
-            // pulsing and draw the black frame, if necessary.
-            updateScrimController();
-        }
-
-        @Override
-        public void stopDozing() {
-            if (mDozingRequested) {
-                mDozingRequested = false;
-                mDozeLog.traceDozing(mDozing);
-                updateDozing();
-            }
-        }
-
-        @Override
-        public void onIgnoreTouchWhilePulsing(boolean ignore) {
-            if (ignore != mIgnoreTouchWhilePulsing) {
-                mDozeLog.tracePulseTouchDisabledByProx(ignore);
-            }
-            mIgnoreTouchWhilePulsing = ignore;
-            if (isDozing() && ignore) {
-                mStatusBarWindowViewController.cancelCurrentTouch();
-            }
-        }
-
-        @Override
-        public void dozeTimeTick() {
-            mNotificationPanel.dozeTimeTick();
-            if (mAmbientIndicationContainer instanceof DozeReceiver) {
-                ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
-            }
-        }
-
-        @Override
-        public boolean isPowerSaveActive() {
-            return mBatteryController.isAodPowerSave();
-        }
-
-        @Override
-        public boolean isPulsingBlocked() {
-            return mBiometricUnlockController.getMode()
-                    == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
-        }
-
-        @Override
-        public boolean isProvisioned() {
-            return mDeviceProvisionedController.isDeviceProvisioned()
-                    && mDeviceProvisionedController.isCurrentUserSetup();
-        }
-
-        @Override
-        public boolean isBlockingDoze() {
-            if (mBiometricUnlockController.hasPendingAuthentication()) {
-                Log.i(TAG, "Blocking AOD because fingerprint has authenticated");
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public void extendPulse(int reason) {
-            if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
-                mScrimController.setWakeLockScreenSensorActive(true);
-            }
-            if (mDozeScrimController.isPulsing() && mHeadsUpManager.hasNotifications()) {
-                mHeadsUpManager.extendHeadsUp();
-            } else {
-                mDozeScrimController.extendPulse();
-            }
-        }
-
-        @Override
-        public void stopPulsing() {
-            if (mDozeScrimController.isPulsing()) {
-                mDozeScrimController.pulseOutNow();
-            }
-        }
-
-        @Override
-        public void setAnimateWakeup(boolean animateWakeup) {
-            if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
-                    || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) {
-                // Too late to change the wakeup animation.
-                return;
-            }
-            mAnimateWakeup = animateWakeup;
-        }
-
-        @Override
-        public void setAnimateScreenOff(boolean animateScreenOff) {
-            mAnimateScreenOff = animateScreenOff;
-        }
-
-        @Override
-        public void onSlpiTap(float screenX, float screenY) {
-            if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
-                && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
-                mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2);
-                float viewX = screenX - mTmpInt2[0];
-                float viewY = screenY - mTmpInt2[1];
-                if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
-                        && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
-                    dispatchTap(mAmbientIndicationContainer, viewX, viewY);
-                }
-            }
-        }
-
-        @Override
-        public void setDozeScreenBrightness(int value) {
-            mStatusBarWindowController.setDozeScreenBrightness(value);
-        }
-
-        @Override
-        public void setAodDimmingScrim(float scrimOpacity) {
-            mScrimController.setAodFrontScrimAlpha(scrimOpacity);
-        }
-
-        @Override
-        public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
-            if (mPendingScreenOffCallback != null) {
-                Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one.");
-            }
-            mPendingScreenOffCallback = onDisplayOffCallback;
-            updateScrimController();
-        }
-
-        @Override
-        public void cancelGentleSleep() {
-            mPendingScreenOffCallback = null;
-            if (mScrimController.getState() == ScrimState.OFF) {
-                updateScrimController();
-            }
-        }
-
-        /**
-         * When the dozing host is waiting for scrims to fade out to change the display state.
-         */
-        boolean hasPendingScreenOffCallback() {
-            return mPendingScreenOffCallback != null;
-        }
-
-        /**
-         * Executes an nullifies the pending display state callback.
-         *
-         * @see #hasPendingScreenOffCallback()
-         * @see #prepareForGentleSleep(Runnable)
-         */
-        void executePendingScreenOffCallback() {
-            if (mPendingScreenOffCallback == null) {
-                return;
-            }
-            mPendingScreenOffCallback.run();
-            mPendingScreenOffCallback = null;
-        }
-
-        private void dispatchTap(View view, float x, float y) {
-            long now = SystemClock.elapsedRealtime();
-            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN);
-            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP);
-        }
-
-        private void dispatchTouchEvent(View view, float x, float y, long now, int action) {
-            MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */);
-            view.dispatchTouchEvent(ev);
-            ev.recycle();
-        }
-
-        private boolean shouldAnimateWakeup() {
-            return mAnimateWakeup;
-        }
-
-        public boolean shouldAnimateScreenOff() {
-            return mAnimateScreenOff;
-        }
-    }
-
     public boolean shouldIgnoreTouch() {
-        return isDozing() && mDozeServiceHost.mIgnoreTouchWhilePulsing;
+        return isDozing() && mDozeServiceHost.getIgnoreTouchWhilePulsing();
     }
 
     // Begin Extra BaseStatusBar methods.
@@ -4406,7 +4110,7 @@
     private boolean mVisibleToUser;
 
     protected DevicePolicyManager mDevicePolicyManager;
-    protected PowerManager mPowerManager;
+    private final PowerManager mPowerManager;
     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     protected KeyguardManager mKeyguardManager;