Combines NotificationEntryManager listener interfaces (part 2).

This change introduces the NotificationAlertingManager component, a
NotificationEntryListener which handles showing/hiding/updating alerts
(heads-up or ambient pulsing) in response to events from the
NotificationEntryManager.  All code in the new component was moved out
of NotificationEntryManager proper.

Test: atest SystemUITests, manual
Change-Id: I46a046da6caf39b1d314b357e21ac6b4755c5796
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f51004a..08fa434 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -54,6 +54,7 @@
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationFilter;
@@ -266,6 +267,8 @@
     @Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler;
     @Inject Lazy<BubbleController> mBubbleController;
     @Inject Lazy<NotificationEntryManager> mNotificationEntryManager;
+    @Inject
+    Lazy<NotificationAlertingManager> mNotificationAlertingManager;
     @Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
     @Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper;
     @Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler;
@@ -439,6 +442,7 @@
                 mRemoteInputQuickSettingsDisabler::get);
         mProviders.put(BubbleController.class, mBubbleController::get);
         mProviders.put(NotificationEntryManager.class, mNotificationEntryManager::get);
+        mProviders.put(NotificationAlertingManager.class, mNotificationAlertingManager::get);
 
         sDependency = this;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
new file mode 100644
index 0000000..c837aa0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2018 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.notification;
+
+import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+
+import android.app.Notification;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import com.android.systemui.statusbar.AlertingNotificationManager;
+import com.android.systemui.statusbar.AmbientPulseManager;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.notification.row.NotificationInflater;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+/** Handles heads-up and pulsing behavior driven by notification changes. */
+@Singleton
+public class NotificationAlertingManager {
+
+    private static final String TAG = "NotifAlertManager";
+
+    private final AmbientPulseManager mAmbientPulseManager;
+    private final NotificationRemoteInputManager mRemoteInputManager;
+    private final VisualStabilityManager mVisualStabilityManager;
+    private final Lazy<ShadeController> mShadeController;
+    private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+    private final NotificationListener mNotificationListener;
+
+    private HeadsUpManager mHeadsUpManager;
+
+    @Inject
+    public NotificationAlertingManager(
+            NotificationEntryManager notificationEntryManager,
+            AmbientPulseManager ambientPulseManager,
+            NotificationRemoteInputManager remoteInputManager,
+            VisualStabilityManager visualStabilityManager,
+            Lazy<ShadeController> shadeController,
+            NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+            NotificationListener notificationListener) {
+        mAmbientPulseManager = ambientPulseManager;
+        mRemoteInputManager = remoteInputManager;
+        mVisualStabilityManager = visualStabilityManager;
+        mShadeController = shadeController;
+        mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+        mNotificationListener = notificationListener;
+
+        notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+            @Override
+            public void onEntryInflated(NotificationData.Entry entry, int inflatedFlags) {
+                showAlertingView(entry, inflatedFlags);
+            }
+
+            @Override
+            public void onEntryUpdated(NotificationData.Entry entry) {
+                updateAlertState(entry);
+            }
+
+            @Override
+            public void onEntryRemoved(NotificationData.Entry entry) {
+                stopAlerting(entry);
+            }
+        });
+    }
+
+    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+        mHeadsUpManager = headsUpManager;
+    }
+
+    /**
+     * Adds the entry to the respective alerting manager if the content view was inflated and
+     * the entry should still alert.
+     *
+     * @param entry         entry to add
+     * @param inflatedFlags flags representing content views that were inflated
+     */
+    private void showAlertingView(NotificationData.Entry entry,
+            @NotificationInflater.InflationFlag int inflatedFlags) {
+        if ((inflatedFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
+            // Possible for shouldHeadsUp to change between the inflation starting and ending.
+            // If it does and we no longer need to heads up, we should free the view.
+            if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
+                mHeadsUpManager.showNotification(entry);
+                // Mark as seen immediately
+                setNotificationShown(entry.notification);
+            } else {
+                entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
+            }
+        }
+        if ((inflatedFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) {
+            if (mNotificationInterruptionStateProvider.shouldPulse(entry)) {
+                mAmbientPulseManager.showNotification(entry);
+            } else {
+                entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT);
+            }
+        }
+    }
+
+    private void updateAlertState(NotificationData.Entry entry) {
+        boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
+        AlertingNotificationManager alertManager;
+        boolean shouldAlert;
+        if (mShadeController.get().isDozing()) {
+            alertManager = mAmbientPulseManager;
+            shouldAlert = mNotificationInterruptionStateProvider.shouldPulse(entry);
+        } else {
+            alertManager = mHeadsUpManager;
+            shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
+        }
+        final boolean wasAlerting = alertManager.isAlerting(entry.key);
+        if (wasAlerting) {
+            if (!shouldAlert) {
+                // We don't want this to be interrupting anymore, let's remove it
+                alertManager.removeNotification(entry.key,
+                        false /* ignoreEarliestRemovalTime */);
+            } else {
+                alertManager.updateNotification(entry.key, alertAgain);
+            }
+        } else if (shouldAlert && alertAgain) {
+            // This notification was updated to be alerting, show it!
+            alertManager.showNotification(entry);
+        }
+    }
+
+    private static boolean alertAgain(
+            NotificationData.Entry oldEntry, Notification newNotification) {
+        return oldEntry == null || !oldEntry.hasInterrupted()
+                || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
+    }
+
+    private void setNotificationShown(StatusBarNotification n) {
+        try {
+            mNotificationListener.setNotificationsShown(new String[]{n.getKey()});
+        } catch (RuntimeException e) {
+            Log.d(TAG, "failed setNotificationsShown: ", e);
+        }
+    }
+
+    private void stopAlerting(NotificationData.Entry entry) {
+        // Attempt to remove notifications from their alert managers (heads up, ambient pulse).
+        // Though the remove itself may fail, it lets the manager know to remove as soon as
+        // possible.
+        if (mHeadsUpManager.isAlerting(entry.key)) {
+            // A cancel() in response to a remote input shouldn't be delayed, as it makes the
+            // sending look longer than it takes.
+            // Also we should not defer the removal if reordering isn't allowed since otherwise
+            // some notifications can't disappear before the panel is closed.
+            boolean ignoreEarliestRemovalTime =
+                    mRemoteInputManager.getController().isSpinning(entry.key)
+                            && !FORCE_REMOTE_INPUT_HISTORY
+                            || !mVisualStabilityManager.isReorderingAllowed();
+            mHeadsUpManager.removeNotification(entry.key, ignoreEarliestRemovalTime);
+        }
+        if (mAmbientPulseManager.isAlerting(entry.key)) {
+            mAmbientPulseManager.removeNotification(entry.key,
+                    false /* ignoreEarliestRemovalTime */);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 361ae8b..fb9cac6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -17,6 +17,8 @@
 
 import android.service.notification.StatusBarNotification;
 
+import com.android.systemui.statusbar.notification.row.NotificationInflater;
+
 /**
  * Listener interface for changes sent by NotificationEntryManager.
  */
@@ -37,7 +39,14 @@
     /**
      * Called when a notification was updated.
      */
-    default void onNotificationUpdated(StatusBarNotification notification) {
+    default void onEntryUpdated(NotificationData.Entry entry) {
+    }
+
+    /**
+     * Called when a notification's views are inflated for the first time.
+     */
+    default void onEntryInflated(NotificationData.Entry entry,
+            @NotificationInflater.InflationFlag int inflatedFlags) {
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 98ddd6b..5935643 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -16,9 +16,6 @@
 package com.android.systemui.statusbar.notification;
 
 import static com.android.systemui.bubbles.BubbleController.DEBUG_DEMOTE_TO_NOTIF;
-import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
 
 import android.annotation.Nullable;
 import android.app.Notification;
@@ -42,10 +39,8 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
-import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -58,7 +53,6 @@
 import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.util.leak.LeakDetector;
@@ -108,8 +102,6 @@
     // Lazily retrieved dependencies
     private NotificationRemoteInputManager mRemoteInputManager;
     private NotificationMediaManager mMediaManager;
-    private NotificationListener mNotificationListener;
-    private ShadeController mShadeController;
     private NotificationRowBinder mNotificationRowBinder;
 
     private final Handler mDeferredNotificationViewUpdateHandler;
@@ -186,20 +178,6 @@
         return mMediaManager;
     }
 
-    private NotificationListener getNotificationListener() {
-        if (mNotificationListener == null) {
-            mNotificationListener = Dependency.get(NotificationListener.class);
-        }
-        return mNotificationListener;
-    }
-
-    private ShadeController getShadeController() {
-        if (mShadeController == null) {
-            mShadeController = Dependency.get(ShadeController.class);
-        }
-        return mShadeController;
-    }
-
     private NotificationRowBinder getRowBinder() {
         if (mNotificationRowBinder == null) {
             mNotificationRowBinder = Dependency.get(NotificationRowBinder.class);
@@ -349,35 +327,6 @@
         }
     }
 
-    /**
-     * Adds the entry to the respective alerting manager if the content view was inflated and
-     * the entry should still alert.
-     *
-     * @param entry entry to add
-     * @param inflatedFlags flags representing content views that were inflated
-     */
-    private void showAlertingView(NotificationData.Entry entry,
-            @InflationFlag int inflatedFlags) {
-        if ((inflatedFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
-            // Possible for shouldHeadsUp to change between the inflation starting and ending.
-            // If it does and we no longer need to heads up, we should free the view.
-            if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
-                mHeadsUpManager.showNotification(entry);
-                // Mark as seen immediately
-                setNotificationShown(entry.notification);
-            } else {
-                entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
-            }
-        }
-        if ((inflatedFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) {
-            if (mNotificationInterruptionStateProvider.shouldPulse(entry)) {
-                mAmbientPulseManager.showNotification(entry);
-            } else {
-                entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT);
-            }
-        }
-    }
-
     @Override
     public void onAsyncInflationFinished(NotificationData.Entry entry,
             @InflationFlag int inflatedFlags) {
@@ -387,7 +336,9 @@
         if (!entry.isRowRemoved()) {
             boolean isNew = mNotificationData.get(entry.key) == null;
             if (isNew) {
-                showAlertingView(entry, inflatedFlags);
+                for (NotificationEntryListener listener : mNotificationEntryListeners) {
+                    listener.onEntryInflated(entry, inflatedFlags);
+                }
                 addEntry(entry);
             } else {
                 if (entry.getRow().hasLowPriorityStateUpdated()) {
@@ -418,23 +369,6 @@
             }
         }
 
-        // Attempt to remove notifications from their alert managers (heads up, ambient pulse).
-        // Though the remove itself may fail, it lets the manager know to remove as soon as
-        // possible.
-        if (mHeadsUpManager.isAlerting(key)) {
-            // A cancel() in response to a remote input shouldn't be delayed, as it makes the
-            // sending look longer than it takes.
-            // Also we should not defer the removal if reordering isn't allowed since otherwise
-            // some notifications can't disappear before the panel is closed.
-            boolean ignoreEarliestRemovalTime = getRemoteInputManager().getController().isSpinning(key)
-                    && !FORCE_REMOTE_INPUT_HISTORY
-                    || !mVisualStabilityManager.isReorderingAllowed();
-            mHeadsUpManager.removeNotification(key, ignoreEarliestRemovalTime);
-        }
-        if (mAmbientPulseManager.isAlerting(key)) {
-            mAmbientPulseManager.removeNotification(key, false /* ignoreEarliestRemovalTime */);
-        }
-
         if (entry == null) {
             mCallback.onNotificationRemoved(key, null /* old */);
             return;
@@ -616,11 +550,6 @@
         }
     }
 
-    private boolean alertAgain(NotificationData.Entry oldEntry, Notification newNotification) {
-        return oldEntry == null || !oldEntry.hasInterrupted()
-                || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
-    }
-
     private void updateNotificationInternal(StatusBarNotification notification,
             NotificationListenerService.RankingMap ranking) throws InflationException {
         if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
@@ -651,14 +580,6 @@
         mForegroundServiceController.updateNotification(notification,
                 mNotificationData.getImportance(key));
 
-        boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
-        if (getShadeController().isDozing()) {
-            updateAlertState(entry, mNotificationInterruptionStateProvider.shouldPulse(entry),
-                    alertAgain, mAmbientPulseManager);
-        } else {
-            updateAlertState(entry, mNotificationInterruptionStateProvider.shouldHeadsUp(entry),
-                    alertAgain, mHeadsUpManager);
-        }
         updateNotifications();
 
         if (!notification.isClearable()) {
@@ -674,7 +595,10 @@
             Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
         }
 
-        mCallback.onNotificationUpdated(notification);
+        for (NotificationEntryListener listener : mNotificationEntryListeners) {
+            listener.onEntryUpdated(entry);
+        }
+        mCallback.onEntryUpdated(entry);
 
         maybeScheduleUpdateNotificationViews(entry);
     }
@@ -739,43 +663,6 @@
         }
     }
 
-    private void setNotificationShown(StatusBarNotification n) {
-        setNotificationsShown(new String[]{n.getKey()});
-    }
-
-    protected void setNotificationsShown(String[] keys) {
-        try {
-            getNotificationListener().setNotificationsShown(keys);
-        } catch (RuntimeException e) {
-            Log.d(TAG, "failed setNotificationsShown: ", e);
-        }
-    }
-
-    /**
-     * Update the entry's alert state and call the appropriate {@link AlertingNotificationManager}
-     * method.
-     * @param entry entry to update
-     * @param shouldAlert whether or not it should be alerting
-     * @param alertAgain whether or not an alert should actually come in as if it were new
-     * @param alertManager the alerting notification manager that manages the alert state
-     */
-    private void updateAlertState(NotificationData.Entry entry, boolean shouldAlert,
-            boolean alertAgain, AlertingNotificationManager alertManager) {
-        final boolean wasAlerting = alertManager.isAlerting(entry.key);
-        if (wasAlerting) {
-            if (!shouldAlert) {
-                // We don't want this to be interrupting anymore, lets remove it
-                alertManager.removeNotification(entry.key,
-                        false /* ignoreEarliestRemovalTime */);
-            } else {
-                alertManager.updateNotification(entry.key, alertAgain);
-            }
-        } else if (shouldAlert && alertAgain) {
-            // This notification was updated to be alerting, show it!
-            alertManager.showNotification(entry);
-        }
-    }
-
     /**
      * @return An iterator for all "pending" notifications. Pending notifications are newly-posted
      * notifications whose views have not yet been inflated. In general, the system pretends like
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 cf12fc77..8d23c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -187,6 +187,7 @@
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationClicker;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationData.Entry;
@@ -385,6 +386,8 @@
     protected AppOpsController mAppOpsController;
     protected KeyguardViewMediator mKeyguardViewMediator;
     private ZenModeController mZenController;
+    private final NotificationAlertingManager mNotificationAlertingManager =
+            Dependency.get(NotificationAlertingManager.class);
 
     // for disabling the status bar
     private int mDisabled1 = 0;
@@ -1036,7 +1039,8 @@
 
         mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
                 mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
-                mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager);
+                mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager,
+                mNotificationAlertingManager);
 
         mAppOpsController.addCallback(APP_OPS, this);
         mNotificationListener.setUpWithPresenter(mPresenter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index d643f07..e1a948e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationData.Entry;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -129,7 +130,8 @@
             DozeScrimController dozeScrimController,
             ScrimController scrimController,
             ActivityLaunchAnimator activityLaunchAnimator,
-            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            NotificationAlertingManager notificationAlertingManager) {
         mContext = context;
         mNotificationPanel = panel;
         mHeadsUpManager = headsUp;
@@ -181,7 +183,7 @@
                 }
 
                 @Override
-                public void onNotificationUpdated(StatusBarNotification notification) {
+                public void onEntryUpdated(Entry entry) {
                     mShadeController.updateAreThereNotifications();
                 }
 
@@ -212,6 +214,8 @@
             onUserSwitched(mLockscreenUserManager.getCurrentUserId());
         });
         Dependency.get(ConfigurationController.class).addCallback(this);
+
+        notificationAlertingManager.setHeadsUpManager(mHeadsUpManager);
     }
 
     @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 701ea7d..f33a48f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -300,7 +300,7 @@
 
         verify(mPresenter).updateNotificationViews();
         verify(mForegroundServiceController).updateNotification(eq(mSbn), anyInt());
-        verify(mCallback).onNotificationUpdated(mSbn);
+        verify(mCallback).onEntryUpdated(mEntry);
         assertNotNull(mEntry.getRow());
         assertEquals(mEntry.userSentiment,
                 NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 02f8949..4fabe7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -37,6 +37,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -70,7 +71,8 @@
                 mock(NotificationPanelView.class), mock(HeadsUpManagerPhone.class),
                 statusBarWindowView, mock(NotificationListContainerViewGroup.class),
                 mock(DozeScrimController.class), mock(ScrimController.class),
-                mock(ActivityLaunchAnimator.class), mock(StatusBarKeyguardViewManager.class));
+                mock(ActivityLaunchAnimator.class), mock(StatusBarKeyguardViewManager.class),
+                mock(NotificationAlertingManager.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index fd795e5..1f4a8ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -91,6 +91,7 @@
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationData.Entry;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -153,6 +154,8 @@
     @Mock private BubbleController mBubbleController;
     @Mock
     private NotificationFilter mNotificationFilter;
+    @Mock
+    private NotificationAlertingManager mNotificationAlertingManager;
 
     private TestableStatusBar mStatusBar;
     private FakeMetricsLogger mMetricsLogger;
@@ -180,6 +183,8 @@
                 mDeviceProvisionedController);
         mDependency.injectMockDependency(BubbleController.class);
         mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter);
+        mDependency.injectTestDependency(NotificationAlertingManager.class,
+                mNotificationAlertingManager);
 
         IPowerManager powerManagerService = mock(IPowerManager.class);
         mPowerManager = new PowerManager(mContext, powerManagerService,