Remove NotificationData

Ye olde NotificationData class was responsible for a few general things:
- Keep a list of visible `NotificationEntry`s
- Filter / sort the visible entries
- Keep a sorted / filtered list of those entries
- Answer lots of questions about the entries themselves (rank,
isAmbient, list of entries for current user, etc.)
- Keep track of the current RankingMap
- Set priority buckets on entries
- Tell the group manager when things changed

The basic idea here is to remove NotificationData in favor of 3 other
changes:

1. Any place which needed to query NotificationData for info about the
entry (in particular its ranking) can just ask the entry for it now.
Entries all keep a reference to their rank

2. NotificationEntryManager now just maintains its own list of visible
notifications. It was already the point of contact to get a handle to
NotificationData so this makes call sites simpler.

3. Create a simpler NotificationRankingManager (maybe delete this
eventually) to encapsulate the sorting logic and hang on to the latest
RankingMap

Test: atest SystemUITests
Change-Id: I14073e103c6d50da37207ca8fd86828da0aaaff9
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index dca5c8a..1a0690c 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -75,10 +75,10 @@
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.NotificationFilter;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController;
 import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index 385de4a..15a5c27 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -139,8 +139,7 @@
         // Update appOp if there's an associated pending or visible notification:
         final String foregroundKey = getStandardLayoutKey(userId, packageName);
         if (foregroundKey != null) {
-            final NotificationEntry entry = mEntryManager.getPendingOrCurrentNotif(
-                    foregroundKey);
+            final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(foregroundKey);
             if (entry != null
                     && uid == entry.getSbn().getUid()
                     && packageName.equals(entry.getSbn().getPackageName())) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 9f7bdd4..1052a99 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -78,7 +78,6 @@
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -352,14 +351,13 @@
      * @param userId the id of the user
      */
     private void restoreBubbles(@UserIdInt int userId) {
-        NotificationData notificationData =
-                mNotificationEntryManager.getNotificationData();
         ArraySet<String> savedBubbleKeys = mSavedBubbleKeysPerUser.get(userId);
         if (savedBubbleKeys == null) {
             // There were no bubbles saved for this used.
             return;
         }
-        for (NotificationEntry e : notificationData.getNotificationsForCurrentUser()) {
+        for (NotificationEntry e :
+                mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
             if (savedBubbleKeys.contains(e.getKey())
                     && mNotificationInterruptionStateProvider.shouldBubbleUp(e)
                     && canLaunchInActivityView(mContext, e)) {
@@ -458,7 +456,7 @@
     public boolean isBubbleNotificationSuppressedFromShade(String key) {
         boolean isBubbleAndSuppressed = mBubbleData.hasBubbleWithKey(key)
                 && !mBubbleData.getBubbleWithKey(key).showInShadeWhenBubble();
-        NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
+        NotificationEntry entry = mNotificationEntryManager.getActiveNotificationUnfiltered(key);
         String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
         boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey);
         boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey));
@@ -571,7 +569,8 @@
             new NotificationRemoveInterceptor() {
             @Override
             public boolean onNotificationRemoveRequested(String key, int reason) {
-                NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
+                NotificationEntry entry =
+                        mNotificationEntryManager.getActiveNotificationUnfiltered(key);
                 String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
                 ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
 
@@ -768,7 +767,7 @@
                         String notifKey = mBubbleData.getSummaryKey(groupKey);
                         mBubbleData.removeSuppressedSummary(groupKey);
                         NotificationEntry entry =
-                                mNotificationEntryManager.getNotificationData().get(notifKey);
+                                mNotificationEntryManager.getActiveNotificationUnfiltered(notifKey);
                         mNotificationEntryManager.performRemoveNotification(
                                 entry.getSbn(), UNDEFINED_DISMISS_REASON);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
index 6744d74..7007f9d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
@@ -35,6 +35,7 @@
 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.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -50,6 +51,7 @@
 import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.HotspotControllerImpl;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -257,4 +259,7 @@
     @Binds
     public abstract VolumeComponent provideVolumeComponent(
             VolumeDialogComponent volumeDialogComponent);
+    /** */
+    @Binds
+    public abstract HeadsUpManager bindHeadsUpManager(HeadsUpManagerPhone headsUpManagerPhone);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 48c72d3..f1d02bb 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -33,7 +33,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -74,7 +74,7 @@
     abstract DockManager bindDockManager(DockManagerImpl dockManager);
 
     @Binds
-    abstract NotificationData.KeyguardEnvironment bindKeyguardEnvironment(
+    abstract NotificationEntryManager.KeyguardEnvironment bindKeyguardEnvironment(
             KeyguardEnvironmentImpl keyguardEnvironment);
 
     @Binds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index c4de2d3..98a2675 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -110,8 +110,7 @@
                 }
 
                 String key = sbn.getKey();
-                boolean isUpdate =
-                        mEntryManager.getNotificationData().get(key) != null;
+                boolean isUpdate = mEntryManager.getActiveNotificationUnfiltered(key) != null;
                 // In case we don't allow child notifications, we ignore children of
                 // notifications that have a summary, since` we're not going to show them
                 // anyway. This is true also when the summary is canceled,
@@ -126,8 +125,7 @@
                     if (isUpdate) {
                         mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);
                     } else {
-                        mEntryManager.getNotificationData()
-                                .updateRanking(rankingMap, "onNotificationPosted");
+                        mEntryManager.updateRanking(rankingMap, "onNotificationPosted");
                     }
                     return;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 571d3d7..021e7e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.statusbar;
 
+import static android.app.Notification.VISIBILITY_SECRET;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -126,7 +127,7 @@
                 updatePublicMode();
                 // The filtering needs to happen before the update call below in order to make sure
                 // the presenter has the updated notifications from the new user
-                getEntryManager().getNotificationData().filterAndSort("user switched");
+                getEntryManager().reapplyFilterAndSort("user switched");
                 mPresenter.onUserSwitched(mCurrentUserId);
 
                 for (UserChangedListener listener : mListeners) {
@@ -148,17 +149,17 @@
                     }
                 }
                 if (notificationKey != null) {
-                    final int count =
-                            getEntryManager().getNotificationData().getActiveNotifications().size();
-                    final int rank = getEntryManager().getNotificationData().getRank(notificationKey);
+                    NotificationEntry entry =
+                            getEntryManager().getActiveNotificationUnfiltered(notificationKey);
+                    final int count = getEntryManager().getActiveNotificationsCount();
+                    final int rank = entry != null ? entry.getRanking().getRank() : 0;
                     NotificationVisibility.NotificationLocation location =
-                            NotificationLogger.getNotificationLocation(
-                                    getEntryManager().getNotificationData().get(notificationKey));
+                            NotificationLogger.getNotificationLocation(entry);
                     final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
                             rank, count, true, location);
                     try {
                         mBarService.onNotificationClick(notificationKey, nv);
-                    } catch (RemoteException e) {
+                    } catch (RemoteException exception) {
                         /* ignore */
                     }
                 }
@@ -311,9 +312,9 @@
             Log.wtf(TAG, "mEntryManager was null!", new Throwable());
             return true;
         }
-        return isLockscreenPublicMode(mCurrentUserId)
-                && getEntryManager().getNotificationData().getVisibilityOverride(key) ==
-                        Notification.VISIBILITY_SECRET;
+        NotificationEntry visibleEntry = getEntryManager().getActiveNotificationUnfiltered(key);
+        return isLockscreenPublicMode(mCurrentUserId) && visibleEntry != null
+                && visibleEntry.getRanking().getVisibilityOverride() == VISIBILITY_SECRET;
     }
 
     public boolean shouldShowOnKeyguard(NotificationEntry entry) {
@@ -326,8 +327,7 @@
                 && hideSilentNotificationsOnLockscreen()) {
             exceedsPriorityThreshold = entry.getBucket() != BUCKET_SILENT;
         } else {
-            exceedsPriorityThreshold =
-                    !getEntryManager().getNotificationData().isAmbient(entry.getKey());
+            exceedsPriorityThreshold = !entry.getRanking().isAmbient();
         }
         return mShowLockscreenNotifications && exceedsPriorityThreshold;
     }
@@ -467,8 +467,9 @@
             Log.wtf(TAG, "mEntryManager was null!", new Throwable());
             return true;
         }
-        return getEntryManager().getNotificationData().getVisibilityOverride(key) ==
-                Notification.VISIBILITY_PRIVATE;
+        NotificationEntry entry = getEntryManager().getActiveNotificationUnfiltered(key);
+        return entry != null
+                && entry.getRanking().getVisibilityOverride() == Notification.VISIBILITY_PRIVATE;
     }
 
     private void updateCurrentProfilesCache() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index d668665..a98f826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -102,8 +102,7 @@
     }
 
 
-    // Late binding
-    private NotificationEntryManager mEntryManager;
+    private final NotificationEntryManager mEntryManager;
 
     // Late binding, also @Nullable due to being in com.android.systemui.statusbar.phone package
     @Nullable
@@ -258,8 +257,9 @@
         if (mMediaNotificationKey == null) {
             return null;
         }
-        synchronized (mEntryManager.getNotificationData()) {
-            NotificationEntry entry = mEntryManager.getNotificationData().get(mMediaNotificationKey);
+        synchronized (mEntryManager) {
+            NotificationEntry entry = mEntryManager
+                    .getActiveNotificationUnfiltered(mMediaNotificationKey);
             if (entry == null || entry.expandedIcon == null) {
                 return null;
             }
@@ -281,8 +281,9 @@
     public void findAndUpdateMediaNotifications() {
         boolean metaDataChanged = false;
 
-        synchronized (mEntryManager.getNotificationData()) {
-            Set<NotificationEntry> allNotifications = mEntryManager.getAllNotifs();
+        synchronized (mEntryManager) {
+            Set<NotificationEntry> allNotifications =
+                    mEntryManager.getPendingAndActiveNotifications();
 
             // Promote the media notification with a controller in 'playing' state, if any.
             NotificationEntry mediaNotification = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 35f06f9..e10d27b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -184,8 +184,9 @@
                 ViewGroup actionGroup = (ViewGroup) parent;
                 buttonIndex = actionGroup.indexOfChild(view);
             }
-            final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
-            final int rank = mEntryManager.getNotificationData().getRank(key);
+            final int count = mEntryManager.getActiveNotificationsCount();
+            final int rank = mEntryManager
+                    .getActiveNotificationUnfiltered(key).getRanking().getRank();
 
             // Notification may be updated before this function is executed, and thus play safe
             // here and verify that the action object is still the one that where the click happens.
@@ -202,7 +203,7 @@
             }
             NotificationVisibility.NotificationLocation location =
                     NotificationLogger.getNotificationLocation(
-                            mEntryManager.getNotificationData().get(key));
+                            mEntryManager.getActiveNotificationUnfiltered(key));
             final NotificationVisibility nv =
                     NotificationVisibility.obtain(key, rank, count, true, location);
             try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 20a3e35..ef733a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -140,8 +140,7 @@
         Assert.isMainThread();
         beginUpdate();
 
-        ArrayList<NotificationEntry> activeNotifications = mEntryManager.getNotificationData()
-                .getActiveNotifications();
+        List<NotificationEntry> activeNotifications = mEntryManager.getVisibleNotifications();
         ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
         final int N = activeNotifications.size();
         for (int i = 0; i < N; i++) {
@@ -339,7 +338,7 @@
                 }
                 for (ExpandableNotificationRow remove : toRemove) {
                     parent.removeChildNotification(remove);
-                    if (mEntryManager.getNotificationData().get(
+                    if (mEntryManager.getActiveNotificationUnfiltered(
                             remove.getStatusBarNotification().getKey()) == null) {
                         // We only want to add an animation if the view is completely removed
                         // otherwise it's just a transfer
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 7bdb21d..40f8e39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -73,8 +73,8 @@
     public void smartActionClicked(
             NotificationEntry entry, int actionIndex, Notification.Action action,
             boolean generatedByAssistant) {
-        final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
-        final int rank = mEntryManager.getNotificationData().getRank(entry.getKey());
+        final int count = mEntryManager.getActiveNotificationsCount();
+        final int rank = entry.getRanking().getRank();
         NotificationVisibility.NotificationLocation location =
                 NotificationLogger.getNotificationLocation(entry);
         final NotificationVisibility nv = NotificationVisibility.obtain(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
index 314dc04..015c323 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
@@ -37,14 +37,14 @@
  */
 @Singleton
 class BypassHeadsUpNotifier @Inject constructor(
-        private val context: Context,
-        private val bypassController: KeyguardBypassController,
-        private val statusBarStateController: StatusBarStateController,
-        private val headsUpManager: HeadsUpManagerPhone,
-        private val notificationLockscreenUserManager: NotificationLockscreenUserManager,
-        private val mediaManager: NotificationMediaManager,
-        tunerService: TunerService) : StatusBarStateController.StateListener,
-        NotificationMediaManager.MediaListener {
+    private val context: Context,
+    private val bypassController: KeyguardBypassController,
+    private val statusBarStateController: StatusBarStateController,
+    private val headsUpManager: HeadsUpManagerPhone,
+    private val notificationLockscreenUserManager: NotificationLockscreenUserManager,
+    private val mediaManager: NotificationMediaManager,
+    tunerService: TunerService
+) : StatusBarStateController.StateListener, NotificationMediaManager.MediaListener {
 
     private lateinit var entryManager: NotificationEntryManager
     private var currentMediaEntry: NotificationEntry? = null
@@ -77,7 +77,8 @@
 
     override fun onMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
         val previous = currentMediaEntry
-        var newEntry = entryManager.notificationData.get(mediaManager.mediaNotificationKey)
+        var newEntry = entryManager
+                .getActiveNotificationUnfiltered(mediaManager.mediaNotificationKey)
         if (!NotificationMediaManager.isPlayingState(state)) {
             newEntry = null
         }
@@ -101,7 +102,7 @@
      */
     private fun canAutoHeadsUp(entry: NotificationEntry): Boolean {
         if (!isAutoHeadsUpAllowed()) {
-            return false;
+            return false
         }
         if (entry.isSensitive) {
             // filter sensitive notifications
@@ -111,7 +112,7 @@
             // filter notifications invisible on Keyguard
             return false
         }
-        if (!entryManager.notificationData.activeNotifications.contains(entry)) {
+        if (entryManager.getActiveNotificationUnfiltered(entry.key) != null) {
             // filter notifications not the active list currently
             return false
         }
@@ -125,7 +126,7 @@
     /**
      * @return {@code true} if autoHeadsUp is possible right now.
      */
-    private fun isAutoHeadsUpAllowed() : Boolean {
+    private fun isAutoHeadsUpAllowed(): Boolean {
         if (!enabled) {
             return false
         }
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 df78fa3..0694920 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -99,7 +99,8 @@
     /**
      * Called whenever notification ranking changes, in response to
      * {@link NotificationListenerService#onNotificationRankingUpdate}. This is called after
-     * NotificationData has processed the update and notifications have been re-sorted and filtered.
+     * NotificationEntryManager has processed the update and notifications have been re-sorted
+     * and filtered.
      *
      * @param rankingMap provides access to ranking information on currently active notifications
      */
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 13d90ff..7a58097 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -18,10 +18,12 @@
 import static android.service.notification.NotificationListenerService.REASON_CANCEL;
 import static android.service.notification.NotificationListenerService.REASON_ERROR;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Notification;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -36,9 +38,8 @@
 import com.android.systemui.statusbar.NotificationRemoveInterceptor;
 import com.android.systemui.statusbar.NotificationUiAdjustment;
 import com.android.systemui.statusbar.NotificationUpdateHandler;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
-import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.logging.NotifEvent;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
@@ -46,12 +47,15 @@
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.util.Assert;
 import com.android.systemui.util.leak.LeakDetector;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -62,9 +66,29 @@
 import javax.inject.Singleton;
 
 /**
- * NotificationEntryManager is responsible for the adding, removing, and updating of notifications.
- * It also handles tasks such as their inflation and their interaction with other
- * Notification.*Manager objects.
+ * NotificationEntryManager is responsible for the adding, removing, and updating of
+ * {@link NotificationEntry}s. It also handles tasks such as their inflation and their interaction
+ * with other Notification.*Manager objects.
+ *
+ * We track notification entries through this lifecycle:
+ *      1. Pending
+ *      2. Active
+ *      3. Sorted / filtered (visible)
+ *
+ * Every entry spends some amount of time in the pending state, while it is being inflated. Once
+ * inflated, an entry moves into the active state, where it _could_ potentially be shown to the
+ * user. After an entry makes its way into the active state, we sort and filter the entire set to
+ * repopulate the visible set.
+ *
+ * There are a few different things that other classes may be interested in, and most of them
+ * involve the current set of notifications. Here's a brief overview of things you may want to know:
+ * @see #getVisibleNotifications() for the visible set
+ * @see #getActiveNotificationUnfiltered(String) to check if a key exists
+ * @see #getPendingNotificationsIterator() for an iterator over the pending notifications
+ * @see #getPendingOrActiveNotif(String) to find a notification exists for that key in any list
+ * @see #getPendingAndActiveNotifications() to get the entire set of Notifications that we're
+ * aware of
+ * @see #getActiveNotificationsForCurrentUser() to see every notification that the current user owns
  */
 @Singleton
 public class NotificationEntryManager implements
@@ -78,12 +102,23 @@
     /**
      * Used when a notification is removed and it doesn't have a reason that maps to one of the
      * reasons defined in NotificationListenerService
-     * (e.g. {@link NotificationListenerService.REASON_CANCEL})
+     * (e.g. {@link NotificationListenerService#REASON_CANCEL})
      */
     public static final int UNDEFINED_DISMISS_REASON = 0;
 
+    /** Pending notifications are ones awaiting inflation */
     @VisibleForTesting
     protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>();
+    /**
+     * Active notifications have been inflated / prepared and could become visible, but may get
+     * filtered out if for instance they are not for the current user
+     */
+    private final ArrayMap<String, NotificationEntry> mActiveNotifications = new ArrayMap<>();
+    @VisibleForTesting
+    /** This is the list of "active notifications for this user in this context" */
+    protected final ArrayList<NotificationEntry> mSortedAndFiltered = new ArrayList<>();
+    private final List<NotificationEntry> mReadOnlyNotifications =
+            Collections.unmodifiableList(mSortedAndFiltered);
 
     private final Map<NotificationEntry, NotificationLifetimeExtender> mRetainedNotifications =
             new ArrayMap<>();
@@ -92,10 +127,12 @@
     private NotificationRemoteInputManager mRemoteInputManager;
     private NotificationRowBinder mNotificationRowBinder;
 
+    private final KeyguardEnvironment mKeyguardEnvironment;
+    private final NotificationGroupManager mGroupManager;
+    private final NotificationRankingManager mRankingManager;
+
     private NotificationPresenter mPresenter;
-    private NotificationListenerService.RankingMap mLatestRankingMap;
-    @VisibleForTesting
-    protected NotificationData mNotificationData;
+    private RankingMap mLatestRankingMap;
     private NotifLog mNotifLog;
 
     @VisibleForTesting
@@ -129,10 +166,14 @@
 
     @Inject
     public NotificationEntryManager(
-            NotificationData notificationData,
-            NotifLog notifLog) {
-        mNotificationData = notificationData;
+            NotifLog notifLog,
+            NotificationGroupManager groupManager,
+            NotificationRankingManager rankingManager,
+            KeyguardEnvironment keyguardEnvironment) {
         mNotifLog = notifLog;
+        mGroupManager = groupManager;
+        mRankingManager = rankingManager;
+        mKeyguardEnvironment = keyguardEnvironment;
     }
 
     /** Adds a {@link NotificationEntryListener}. */
@@ -171,7 +212,6 @@
             NotificationListContainer listContainer,
             HeadsUpManager headsUpManager) {
         mPresenter = presenter;
-        mNotificationData.setHeadsUpManager(headsUpManager);
     }
 
     /** Adds multiple {@link NotificationLifetimeExtender}s. */
@@ -188,10 +228,6 @@
                 UNDEFINED_DISMISS_REASON));
     }
 
-    public NotificationData getNotificationData() {
-        return mNotificationData;
-    }
-
     @Override
     public void onReorderingAllowed() {
         updateNotifications("reordering is now allowed");
@@ -212,10 +248,17 @@
     }
 
     private NotificationVisibility obtainVisibility(String key) {
-        final int rank = mNotificationData.getRank(key);
-        final int count = mNotificationData.getActiveNotifications().size();
+        NotificationEntry e = mActiveNotifications.get(key);
+        final int rank;
+        if (e != null) {
+            rank = e.getRanking().getRank();
+        } else {
+            rank = 0;
+        }
+
+        final int count = mActiveNotifications.size();
         NotificationVisibility.NotificationLocation location =
-                NotificationLogger.getNotificationLocation(getNotificationData().get(key));
+                NotificationLogger.getNotificationLocation(getActiveNotificationUnfiltered(key));
         return NotificationVisibility.obtain(key, rank, count, true, location);
     }
 
@@ -227,7 +270,7 @@
             mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.getSbn(), null,
                     "PendingNotification aborted. " + reason);
         }
-        NotificationEntry addedEntry = mNotificationData.get(key);
+        NotificationEntry addedEntry = getActiveNotificationUnfiltered(key);
         if (addedEntry != null) {
             addedEntry.abortTask();
             mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.getSbn(),
@@ -258,13 +301,13 @@
         // If there was an async task started after the removal, we don't want to add it back to
         // the list, otherwise we might get leaks.
         if (!entry.isRowRemoved()) {
-            boolean isNew = mNotificationData.get(entry.getKey()) == null;
+            boolean isNew = getActiveNotificationUnfiltered(entry.getKey()) == null;
             if (isNew) {
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     mNotifLog.log(NotifEvent.INFLATED, entry);
                     listener.onEntryInflated(entry, inflatedFlags);
                 }
-                mNotificationData.add(entry);
+                addActiveNotification(entry);
                 updateNotifications("onAsyncInflationFinished");
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onNotificationAdded(entry);
@@ -278,8 +321,34 @@
         }
     }
 
+    /**
+     * Equivalent to the old NotificationData#add
+     * @param entry - an entry which is prepared for display
+     */
+    private void addActiveNotification(NotificationEntry entry) {
+        Assert.isMainThread();
+
+        mActiveNotifications.put(entry.getKey(), entry);
+        mGroupManager.onEntryAdded(entry);
+        updateRankingAndSort(mRankingManager.getRankingMap(), "addEntryInternalInternal");
+    }
+
+    /**
+     * Available so that tests can directly manipulate the list of active notifications easily
+     *
+     * @param entry the entry to add directly to the visible notification map
+     */
+    @VisibleForTesting
+    public void addActiveNotificationForTest(NotificationEntry entry) {
+        mActiveNotifications.put(entry.getKey(), entry);
+        mGroupManager.onEntryAdded(entry);
+
+        reapplyFilterAndSort("addVisibleNotification");
+    }
+
+
     @Override
-    public void removeNotification(String key, NotificationListenerService.RankingMap ranking,
+    public void removeNotification(String key, RankingMap ranking,
             int reason) {
         removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */,
                 false /* removedByUser */, reason);
@@ -287,7 +356,7 @@
 
     private void removeNotificationInternal(
             String key,
-            @Nullable NotificationListenerService.RankingMap ranking,
+            @Nullable RankingMap ranking,
             @Nullable NotificationVisibility visibility,
             boolean forceRemove,
             boolean removedByUser,
@@ -300,7 +369,7 @@
             return;
         }
 
-        final NotificationEntry entry = mNotificationData.get(key);
+        final NotificationEntry entry = getActiveNotificationUnfiltered(key);
         boolean lifetimeExtended = false;
 
         // Notification was canceled before it got inflated
@@ -355,8 +424,7 @@
 
                 // Let's remove the children if this was a summary
                 handleGroupSummaryRemoved(key);
-
-                mNotificationData.remove(key, ranking);
+                removeVisibleNotification(key);
                 updateNotifications("removeNotificationInternal");
                 Dependency.get(LeakDetector.class).trackGarbage(entry);
                 removedByUser |= entryDismissed;
@@ -381,7 +449,7 @@
      *
      */
     private void handleGroupSummaryRemoved(String key) {
-        NotificationEntry entry = mNotificationData.get(key);
+        NotificationEntry entry = getActiveNotificationUnfiltered(key);
         if (entry != null && entry.rowExists() && entry.isSummaryWithChildren()) {
             if (entry.getSbn().getOverrideGroupKey() != null && !entry.isRowDismissed()) {
                 // We don't want to remove children for autobundled notifications as they are not
@@ -413,13 +481,14 @@
     }
 
     private void addNotificationInternal(StatusBarNotification notification,
-            NotificationListenerService.RankingMap rankingMap) throws InflationException {
+            RankingMap rankingMap) throws InflationException {
         String key = notification.getKey();
         if (DEBUG) {
             Log.d(TAG, "addNotification key=" + key);
         }
 
-        mNotificationData.updateRanking(rankingMap, "addNotificationInternal");
+        updateRankingAndSort(rankingMap, "addNotificationInternal");
+
         Ranking ranking = new Ranking();
         rankingMap.getRanking(key, ranking);
 
@@ -439,8 +508,7 @@
     }
 
     @Override
-    public void addNotification(StatusBarNotification notification,
-            NotificationListenerService.RankingMap ranking) {
+    public void addNotification(StatusBarNotification notification, RankingMap ranking) {
         try {
             addNotificationInternal(notification, ranking);
         } catch (InflationException e) {
@@ -449,12 +517,12 @@
     }
 
     private void updateNotificationInternal(StatusBarNotification notification,
-            NotificationListenerService.RankingMap ranking) throws InflationException {
+            RankingMap ranking) throws InflationException {
         if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
 
         final String key = notification.getKey();
         abortExistingInflation(key, "updateNotification");
-        NotificationEntry entry = mNotificationData.get(key);
+        NotificationEntry entry = getActiveNotificationUnfiltered(key);
         if (entry == null) {
             return;
         }
@@ -463,7 +531,11 @@
         // to keep its lifetime extended.
         cancelLifetimeExtension(entry);
 
-        mNotificationData.update(entry, ranking, notification, "updateNotificationInternal");
+        updateRankingAndSort(ranking, "updateNotificationInternal");
+        StatusBarNotification oldSbn = entry.getSbn();
+        entry.setSbn(notification);
+        mGroupManager.onEntryUpdated(entry, oldSbn);
+
         mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.getSbn(), entry.getRanking());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPreEntryUpdated(entry);
@@ -486,8 +558,7 @@
     }
 
     @Override
-    public void updateNotification(StatusBarNotification notification,
-            NotificationListenerService.RankingMap ranking) {
+    public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
         try {
             updateNotificationInternal(notification, ranking);
         } catch (InflationException e) {
@@ -500,16 +571,16 @@
      * @param reason why the notifications are updating
      */
     public void updateNotifications(String reason) {
-        mNotificationData.filterAndSort(reason);
+        reapplyFilterAndSort(reason);
         if (mPresenter != null) {
             mPresenter.updateNotificationViews();
         }
     }
 
     @Override
-    public void updateNotificationRanking(NotificationListenerService.RankingMap rankingMap) {
+    public void updateNotificationRanking(RankingMap rankingMap) {
         List<NotificationEntry> entries = new ArrayList<>();
-        entries.addAll(mNotificationData.getActiveNotifications());
+        entries.addAll(getVisibleNotifications());
         entries.addAll(mPendingNotifications.values());
 
         // Has a copy of the current UI adjustments.
@@ -523,7 +594,7 @@
         }
 
         // Populate notification entries from the new rankings.
-        mNotificationData.updateRanking(rankingMap, "updateNotificationRanking");
+        updateRankingAndSort(rankingMap, "updateNotificationRanking");
         updateRankingOfPendingNotifications(rankingMap);
 
         // By comparing the old and new UI adjustments, reinflate the view accordingly.
@@ -542,8 +613,7 @@
         }
     }
 
-    private void updateRankingOfPendingNotifications(
-            @Nullable NotificationListenerService.RankingMap rankingMap) {
+    private void updateRankingOfPendingNotifications(@Nullable RankingMap rankingMap) {
         if (rankingMap == null) {
             return;
         }
@@ -565,23 +635,35 @@
     }
 
     /**
-     * @return all notification we're currently aware of (both pending and visible notifications)
+     * @return all notifications we're currently aware of (both pending and active notifications)
      */
-    public Set<NotificationEntry> getAllNotifs() {
+    public Set<NotificationEntry> getPendingAndActiveNotifications() {
         Set<NotificationEntry> allNotifs = new HashSet<>(mPendingNotifications.values());
-        allNotifs.addAll(mNotificationData.getActiveNotifications());
+        allNotifs.addAll(mSortedAndFiltered);
         return allNotifs;
     }
 
     /**
+     * Use this method to retrieve a notification entry that has been prepared for presentation.
+     * Note that the notification may be filtered out and never shown to the user.
+     *
+     * @see #getVisibleNotifications() for the currently sorted and filtered list
+     *
+     * @return a {@link NotificationEntry} if it has been prepared, else null
+     */
+    public NotificationEntry getActiveNotificationUnfiltered(String key) {
+        return mActiveNotifications.get(key);
+    }
+
+    /**
      * Gets the pending or visible notification entry with the given key. Returns null if
      * notification doesn't exist.
      */
-    public NotificationEntry getPendingOrCurrentNotif(String key) {
+    public NotificationEntry getPendingOrActiveNotif(String key) {
         if (mPendingNotifications.containsKey(key)) {
             return mPendingNotifications.get(key);
         } else {
-            return mNotificationData.get(key);
+            return mActiveNotifications.get(key);
         }
     }
 
@@ -608,4 +690,136 @@
         }
         return mNotificationRowBinder;
     }
+
+    /*
+     * -----
+     * Annexed from NotificationData below:
+     * Some of these methods may be redundant but require some reworking to remove. For now
+     * we'll try to keep the behavior the same and can simplify these interfaces in another pass
+     */
+
+    /** Internalization of NotificationData#remove */
+    private void removeVisibleNotification(String key) {
+        // no need to synchronize if we're on the main thread dawg
+        Assert.isMainThread();
+
+        NotificationEntry removed = mActiveNotifications.remove(key);
+
+        if (removed == null) return;
+        mGroupManager.onEntryRemoved(removed);
+    }
+
+    /** @return list of active notifications filtered for the current user */
+    public List<NotificationEntry> getActiveNotificationsForCurrentUser() {
+        Assert.isMainThread();
+        ArrayList<NotificationEntry> filtered = new ArrayList<>();
+
+        final int len = mActiveNotifications.size();
+        for (int i = 0; i < len; i++) {
+            NotificationEntry entry = mActiveNotifications.valueAt(i);
+            final StatusBarNotification sbn = entry.getSbn();
+            if (!mKeyguardEnvironment.isNotificationForCurrentProfiles(sbn)) {
+                continue;
+            }
+            filtered.add(entry);
+        }
+
+        return filtered;
+    }
+
+    //TODO: Get rid of this in favor of NotificationUpdateHandler#updateNotificationRanking
+    /**
+     * @param rankingMap the {@link RankingMap} to apply to the current notification list
+     * @param reason the reason for calling this method, for {@link NotifLog}
+     */
+    public void updateRanking(RankingMap rankingMap, String reason) {
+        updateRankingAndSort(rankingMap, reason);
+    }
+
+    /** Resorts / filters the current notification set with the current RankingMap */
+    public void reapplyFilterAndSort(String reason) {
+        updateRankingAndSort(mRankingManager.getRankingMap(), reason);
+    }
+
+    /** Calls to NotificationRankingManager and updates mSortedAndFiltered */
+    private void updateRankingAndSort(@NonNull RankingMap rankingMap, String reason) {
+        mSortedAndFiltered.clear();
+        mSortedAndFiltered.addAll(mRankingManager.updateRanking(
+                rankingMap, mActiveNotifications.values(), reason));
+    }
+
+    /** dump the current active notification list. Called from StatusBar */
+    public void dump(PrintWriter pw, String indent) {
+        pw.println("NotificationEntryManager");
+        int filteredLen = mSortedAndFiltered.size();
+        pw.print(indent);
+        pw.println("active notifications: " + filteredLen);
+        int active;
+        for (active = 0; active < filteredLen; active++) {
+            NotificationEntry e = mSortedAndFiltered.get(active);
+            dumpEntry(pw, indent, active, e);
+        }
+        synchronized (mActiveNotifications) {
+            int totalLen = mActiveNotifications.size();
+            pw.print(indent);
+            pw.println("inactive notifications: " + (totalLen - active));
+            int inactiveCount = 0;
+            for (int i = 0; i < totalLen; i++) {
+                NotificationEntry entry = mActiveNotifications.valueAt(i);
+                if (!mSortedAndFiltered.contains(entry)) {
+                    dumpEntry(pw, indent, inactiveCount, entry);
+                    inactiveCount++;
+                }
+            }
+        }
+    }
+
+    private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) {
+        pw.print(indent);
+        pw.println("  [" + i + "] key=" + e.getKey() + " icon=" + e.icon);
+        StatusBarNotification n = e.getSbn();
+        pw.print(indent);
+        pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " importance="
+                + e.getRanking().getImportance());
+        pw.print(indent);
+        pw.println("      notification=" + n.getNotification());
+    }
+
+    /**
+     * This is the answer to the question "what notifications should the user be seeing right now?"
+     * These are sorted and filtered, and directly inform the notification shade what to show
+     *
+     * @return A read-only list of the currently active notifications
+     */
+    public List<NotificationEntry> getVisibleNotifications() {
+        return mReadOnlyNotifications;
+    }
+
+    /** @return A count of the active notifications */
+    public int getActiveNotificationsCount() {
+        return mReadOnlyNotifications.size();
+    }
+
+    /**
+     * @return {@code true} if there is at least one notification that should be visible right now
+     */
+    public boolean hasActiveNotifications() {
+        return mReadOnlyNotifications.size() != 0;
+    }
+
+    /*
+     * End annexation
+     * -----
+     */
+
+
+    /**
+     * Provides access to keyguard state and user settings dependent data.
+     */
+    public interface KeyguardEnvironment {
+        /** true if the device is provisioned (should always be true in practice) */
+        boolean isDeviceProvisioned();
+        /** true if the notification is for the current profiles */
+        boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index b116409..e5f44bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -28,7 +28,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -44,7 +43,7 @@
     private final NotificationGroupManager mGroupManager = Dependency.get(
             NotificationGroupManager.class);
 
-    private NotificationData.KeyguardEnvironment mEnvironment;
+    private NotificationEntryManager.KeyguardEnvironment mEnvironment;
     private ShadeController mShadeController;
     private ForegroundServiceController mFsc;
     private NotificationLockscreenUserManager mUserManager;
@@ -52,9 +51,9 @@
     @Inject
     public NotificationFilter() {}
 
-    private NotificationData.KeyguardEnvironment getEnvironment() {
+    private NotificationEntryManager.KeyguardEnvironment getEnvironment() {
         if (mEnvironment == null) {
-            mEnvironment = Dependency.get(NotificationData.KeyguardEnvironment.class);
+            mEnvironment = Dependency.get(NotificationEntryManager.KeyguardEnvironment.class);
         }
         return mEnvironment;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
deleted file mode 100644
index a0229d1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * 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.notification.collection;
-
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.Person;
-import android.service.notification.NotificationListenerService.Ranking;
-import android.service.notification.NotificationListenerService.RankingMap;
-import android.service.notification.SnoozeCriterion;
-import android.service.notification.StatusBarNotification;
-import android.util.ArrayMap;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.logging.NotifEvent;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Objects;
-
-import javax.inject.Inject;
-
-/**
- * The list of currently displaying notifications.
- */
-public class NotificationData {
-    private static final String TAG = "NotificationData";
-
-    private final NotificationFilter mNotificationFilter = Dependency.get(NotificationFilter.class);
-
-    /**
-     * These dependencies are late init-ed
-     */
-    private KeyguardEnvironment mEnvironment;
-    private NotificationMediaManager mMediaManager;
-
-    private HeadsUpManager mHeadsUpManager;
-
-    private final ArrayMap<String, NotificationEntry> mEntries = new ArrayMap<>();
-    private final ArrayList<NotificationEntry> mSortedAndFiltered = new ArrayList<>();
-
-    private final NotificationGroupManager mGroupManager =
-            Dependency.get(NotificationGroupManager.class);
-
-    private RankingMap mRankingMap;
-    private final Ranking mTmpRanking = new Ranking();
-    private final boolean mUsePeopleFiltering;
-    private final NotifLog mNotifLog;
-    private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
-
-    @Inject
-    public NotificationData(
-            NotificationSectionsFeatureManager sectionsFeatureManager,
-            NotifLog notifLog,
-            PeopleNotificationIdentifier peopleNotificationIdentifier) {
-        mUsePeopleFiltering = sectionsFeatureManager.isFilteringEnabled();
-        mNotifLog = notifLog;
-        mPeopleNotificationIdentifier = peopleNotificationIdentifier;
-    }
-
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
-        mHeadsUpManager = headsUpManager;
-    }
-
-    @VisibleForTesting
-    protected final Comparator<NotificationEntry> mRankingComparator =
-            new Comparator<NotificationEntry>() {
-        @Override
-        public int compare(NotificationEntry a, NotificationEntry b) {
-            final StatusBarNotification na = a.getSbn();
-            final StatusBarNotification nb = b.getSbn();
-            int aRank = getRank(a.getKey());
-            int bRank = getRank(b.getKey());
-
-            boolean aPeople = isPeopleNotification(a);
-            boolean bPeople = isPeopleNotification(b);
-
-            boolean aMedia = isImportantMedia(a);
-            boolean bMedia = isImportantMedia(b);
-
-            boolean aSystemMax = isSystemMax(a);
-            boolean bSystemMax = isSystemMax(b);
-
-            boolean aHeadsUp = a.isRowHeadsUp();
-            boolean bHeadsUp = b.isRowHeadsUp();
-
-            if (mUsePeopleFiltering && aPeople != bPeople) {
-                return aPeople ? -1 : 1;
-            } else if (aHeadsUp != bHeadsUp) {
-                return aHeadsUp ? -1 : 1;
-            } else if (aHeadsUp) {
-                // Provide consistent ranking with headsUpManager
-                return mHeadsUpManager.compare(a, b);
-            } else if (aMedia != bMedia) {
-                // Upsort current media notification.
-                return aMedia ? -1 : 1;
-            } else if (aSystemMax != bSystemMax) {
-                // Upsort PRIORITY_MAX system notifications
-                return aSystemMax ? -1 : 1;
-            } else if (a.isHighPriority() != b.isHighPriority()) {
-                return -1 * Boolean.compare(a.isHighPriority(), b.isHighPriority());
-            } else if (aRank != bRank) {
-                return aRank - bRank;
-            } else {
-                return Long.compare(nb.getNotification().when, na.getNotification().when);
-            }
-        }
-    };
-
-    private KeyguardEnvironment getEnvironment() {
-        if (mEnvironment == null) {
-            mEnvironment = Dependency.get(KeyguardEnvironment.class);
-        }
-        return mEnvironment;
-    }
-
-    private NotificationMediaManager getMediaManager() {
-        if (mMediaManager == null) {
-            mMediaManager = Dependency.get(NotificationMediaManager.class);
-        }
-        return mMediaManager;
-    }
-
-    /**
-     * Returns the sorted list of active notifications (depending on {@link KeyguardEnvironment}
-     *
-     * <p>
-     * This call doesn't update the list of active notifications. Call {@link #filterAndSort()}
-     * when the environment changes.
-     * <p>
-     * Don't hold on to or modify the returned list.
-     */
-    public ArrayList<NotificationEntry> getActiveNotifications() {
-        return mSortedAndFiltered;
-    }
-
-    public ArrayList<NotificationEntry> getNotificationsForCurrentUser() {
-        synchronized (mEntries) {
-            final int len = mEntries.size();
-            ArrayList<NotificationEntry> filteredForUser = new ArrayList<>(len);
-
-            for (int i = 0; i < len; i++) {
-                NotificationEntry entry = mEntries.valueAt(i);
-                final StatusBarNotification sbn = entry.getSbn();
-                if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
-                    continue;
-                }
-                filteredForUser.add(entry);
-            }
-            return filteredForUser;
-        }
-    }
-
-    public NotificationEntry get(String key) {
-        return mEntries.get(key);
-    }
-
-    public void add(NotificationEntry entry) {
-        synchronized (mEntries) {
-            mEntries.put(entry.getSbn().getKey(), entry);
-        }
-        mGroupManager.onEntryAdded(entry);
-
-        updateRankingAndSort(mRankingMap, "addEntry=" + entry.getSbn());
-    }
-
-    public NotificationEntry remove(String key, RankingMap ranking) {
-        NotificationEntry removed;
-        synchronized (mEntries) {
-            removed = mEntries.remove(key);
-        }
-        if (removed == null) return null;
-        mGroupManager.onEntryRemoved(removed);
-        updateRankingAndSort(ranking, "removeEntry=" + removed.getSbn());
-        return removed;
-    }
-
-    /** Updates the given notification entry with the provided ranking. */
-    public void update(
-            NotificationEntry entry,
-            RankingMap ranking,
-            StatusBarNotification notification,
-            String reason) {
-        updateRanking(ranking, reason);
-        final StatusBarNotification oldNotification = entry.getSbn();
-        entry.setSbn(notification);
-        mGroupManager.onEntryUpdated(entry, oldNotification);
-    }
-
-    /**
-     * Update ranking and trigger a re-sort
-     */
-    public void updateRanking(RankingMap ranking, String reason) {
-        updateRankingAndSort(ranking, reason);
-    }
-
-    /**
-     * Returns true if this notification should be displayed in the high-priority notifications
-     * section
-     */
-    public boolean isHighPriority(StatusBarNotification statusBarNotification) {
-        if (mRankingMap != null) {
-            getRanking(statusBarNotification.getKey(), mTmpRanking);
-            if (mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
-                    || hasHighPriorityCharacteristics(
-                            mTmpRanking.getChannel(), statusBarNotification)) {
-                return true;
-            }
-            if (mGroupManager.isSummaryOfGroup(statusBarNotification)) {
-                final ArrayList<NotificationEntry> logicalChildren =
-                        mGroupManager.getLogicalChildren(statusBarNotification);
-                for (NotificationEntry child : logicalChildren) {
-                    if (isHighPriority(child.getSbn())) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean hasHighPriorityCharacteristics(NotificationChannel channel,
-            StatusBarNotification statusBarNotification) {
-
-        if (isImportantOngoing(statusBarNotification.getNotification())
-                || statusBarNotification.getNotification().hasMediaSession()
-                || hasPerson(statusBarNotification.getNotification())
-                || hasStyle(statusBarNotification.getNotification(),
-                Notification.MessagingStyle.class)) {
-            // Users who have long pressed and demoted to silent should not see the notification
-            // in the top section
-            if (channel != null && channel.hasUserSetImportance()) {
-                return false;
-            }
-            return true;
-        }
-
-        return false;
-    }
-
-    private boolean isImportantOngoing(Notification notification) {
-        return notification.isForegroundService()
-                && mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_LOW;
-    }
-
-    private boolean hasStyle(Notification notification, Class targetStyle) {
-        Class<? extends Notification.Style> style = notification.getNotificationStyle();
-        return targetStyle.equals(style);
-    }
-
-    private boolean hasPerson(Notification notification) {
-        // TODO: cache favorite and recent contacts to check contact affinity
-        ArrayList<Person> people = notification.extras != null
-                ? notification.extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST)
-                : new ArrayList<>();
-        return people != null && !people.isEmpty();
-    }
-
-    public boolean isAmbient(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.isAmbient();
-        }
-        return false;
-    }
-
-    public int getVisibilityOverride(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getVisibilityOverride();
-        }
-        return Ranking.VISIBILITY_NO_OVERRIDE;
-    }
-
-    public List<SnoozeCriterion> getSnoozeCriteria(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getSnoozeCriteria();
-        }
-        return null;
-    }
-
-    public NotificationChannel getChannel(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getChannel();
-        }
-        return null;
-    }
-
-    public int getRank(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.getRank();
-        }
-        return 0;
-    }
-
-    private boolean isImportantMedia(NotificationEntry e) {
-        int importance = e.getRanking().getImportance();
-        boolean media = e.getKey().equals(getMediaManager().getMediaNotificationKey())
-                && importance > NotificationManager.IMPORTANCE_MIN;
-
-        return media;
-    }
-
-    private boolean isSystemMax(NotificationEntry e) {
-        int importance = e.getRanking().getImportance();
-        boolean sys = importance  >= NotificationManager.IMPORTANCE_HIGH
-                && isSystemNotification(e.getSbn());
-
-        return sys;
-    }
-
-    public boolean shouldHide(String key) {
-        if (mRankingMap != null) {
-            getRanking(key, mTmpRanking);
-            return mTmpRanking.isSuspended();
-        }
-        return false;
-    }
-
-    private void updateRankingAndSort(RankingMap rankingMap, String reason) {
-        if (rankingMap != null) {
-            mRankingMap = rankingMap;
-            synchronized (mEntries) {
-                final int len = mEntries.size();
-                for (int i = 0; i < len; i++) {
-                    NotificationEntry entry = mEntries.valueAt(i);
-                    Ranking newRanking = new Ranking();
-                    if (!getRanking(entry.getKey(), newRanking)) {
-                        continue;
-                    }
-                    entry.setRanking(newRanking);
-
-                    final StatusBarNotification oldSbn = entry.getSbn().cloneLight();
-                    final String overrideGroupKey = newRanking.getOverrideGroupKey();
-                    if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
-                        entry.getSbn().setOverrideGroupKey(overrideGroupKey);
-                        mGroupManager.onEntryUpdated(entry, oldSbn);
-                    }
-                    entry.setIsHighPriority(isHighPriority(entry.getSbn()));
-                }
-            }
-        }
-        filterAndSort(reason);
-    }
-
-    /**
-     * Get the ranking from the current ranking map.
-     *
-     * @param key the key to look up
-     * @param outRanking the ranking to populate
-     *
-     * @return {@code true} if the ranking was properly obtained.
-     */
-    @VisibleForTesting
-    protected boolean getRanking(String key, Ranking outRanking) {
-        return mRankingMap.getRanking(key, outRanking);
-    }
-
-    // TODO: This should not be public. Instead the Environment should notify this class when
-    // anything changed, and this class should call back the UI so it updates itself.
-    /**
-     * Filters and sorts the list of notification entries
-     */
-    public void filterAndSort(String reason) {
-        mNotifLog.log(NotifEvent.FILTER_AND_SORT, reason);
-        mSortedAndFiltered.clear();
-
-        synchronized (mEntries) {
-            final int len = mEntries.size();
-            for (int i = 0; i < len; i++) {
-                NotificationEntry entry = mEntries.valueAt(i);
-
-                if (mNotificationFilter.shouldFilterOut(entry)) {
-                    continue;
-                }
-
-                mSortedAndFiltered.add(entry);
-            }
-        }
-
-        Collections.sort(mSortedAndFiltered, mRankingComparator);
-
-        int bucket = BUCKET_PEOPLE;
-        for (NotificationEntry e : mSortedAndFiltered) {
-            assignBucketForEntry(e);
-            if (e.getBucket() < bucket) {
-                android.util.Log.wtf(TAG, "Detected non-contiguous bucket!");
-            }
-            bucket = e.getBucket();
-        }
-    }
-
-    private void assignBucketForEntry(NotificationEntry e) {
-        boolean isHeadsUp = e.isRowHeadsUp();
-        boolean isMedia = isImportantMedia(e);
-        boolean isSystemMax = isSystemMax(e);
-
-        setBucket(e, isHeadsUp, isMedia, isSystemMax);
-    }
-
-    private void setBucket(
-            NotificationEntry e,
-            boolean isHeadsUp,
-            boolean isMedia,
-            boolean isSystemMax) {
-        if (mUsePeopleFiltering && isPeopleNotification(e)) {
-            e.setBucket(BUCKET_PEOPLE);
-        } else if (isHeadsUp || isMedia || isSystemMax || e.isHighPriority()) {
-            e.setBucket(BUCKET_ALERTING);
-        } else {
-            e.setBucket(BUCKET_SILENT);
-        }
-    }
-
-    private boolean isPeopleNotification(NotificationEntry e) {
-        return mPeopleNotificationIdentifier.isPeopleNotification(e.getSbn());
-    }
-
-    public void dump(PrintWriter pw, String indent) {
-        int filteredLen = mSortedAndFiltered.size();
-        pw.print(indent);
-        pw.println("active notifications: " + filteredLen);
-        int active;
-        for (active = 0; active < filteredLen; active++) {
-            NotificationEntry e = mSortedAndFiltered.get(active);
-            dumpEntry(pw, indent, active, e);
-        }
-        synchronized (mEntries) {
-            int totalLen = mEntries.size();
-            pw.print(indent);
-            pw.println("inactive notifications: " + (totalLen - active));
-            int inactiveCount = 0;
-            for (int i = 0; i < totalLen; i++) {
-                NotificationEntry entry = mEntries.valueAt(i);
-                if (!mSortedAndFiltered.contains(entry)) {
-                    dumpEntry(pw, indent, inactiveCount, entry);
-                    inactiveCount++;
-                }
-            }
-        }
-    }
-
-    private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) {
-        getRanking(e.getKey(), mTmpRanking);
-        pw.print(indent);
-        pw.println("  [" + i + "] key=" + e.getKey() + " icon=" + e.icon);
-        StatusBarNotification n = e.getSbn();
-        pw.print(indent);
-        pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " importance="
-                + mTmpRanking.getImportance());
-        pw.print(indent);
-        pw.println("      notification=" + n.getNotification());
-    }
-
-    private static boolean isSystemNotification(StatusBarNotification sbn) {
-        String sbnPackage = sbn.getPackageName();
-        return "android".equals(sbnPackage) || "com.android.systemui".equals(sbnPackage);
-    }
-
-    /**
-     * Provides access to keyguard state and user settings dependent data.
-     */
-    public interface KeyguardEnvironment {
-        boolean isDeviceProvisioned();
-        boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
new file mode 100644
index 0000000..8bce528
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
@@ -0,0 +1,260 @@
+/*
+ * 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.notification.collection
+
+import android.app.Notification
+import android.app.NotificationManager.IMPORTANCE_DEFAULT
+import android.app.NotificationManager.IMPORTANCE_HIGH
+import android.app.NotificationManager.IMPORTANCE_LOW
+import android.app.NotificationManager.IMPORTANCE_MIN
+import android.app.Person
+import android.service.notification.NotificationListenerService.Ranking
+import android.service.notification.NotificationListenerService.RankingMap
+import android.service.notification.StatusBarNotification
+import com.android.internal.annotations.VisibleForTesting
+
+import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.notification.NotificationFilter
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
+import com.android.systemui.statusbar.notification.logging.NotifEvent
+import com.android.systemui.statusbar.notification.logging.NotifLog
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
+import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.policy.HeadsUpManager
+
+import java.util.Objects
+import java.util.ArrayList
+
+import javax.inject.Inject
+
+import kotlin.Comparator
+
+import dagger.Lazy
+
+private const val TAG = "NotifRankingManager"
+
+/**
+ * NotificationRankingManager is responsible for holding on to the most recent [RankingMap], and
+ * updating SystemUI's set of [NotificationEntry]s with their own ranking. It also sorts and filters
+ * a set of entries (but retains none of them). We also set buckets on the entries here since
+ * bucketing is tied closely to sorting.
+ *
+ * For the curious: this class is one iteration closer to null of what used to be called
+ * NotificationData.java.
+ */
+open class NotificationRankingManager @Inject constructor(
+    private val mediaManagerLazy: Lazy<NotificationMediaManager>,
+    private val groupManager: NotificationGroupManager,
+    private val headsUpManager: HeadsUpManager,
+    private val notifFilter: NotificationFilter,
+    private val notifLog: NotifLog,
+    sectionsFeatureManager: NotificationSectionsFeatureManager
+) {
+
+    var rankingMap: RankingMap? = null
+        protected set
+    private val mediaManager by lazy {
+        mediaManagerLazy.get()
+    }
+    private val usePeopleFiltering: Boolean = sectionsFeatureManager.isFilteringEnabled()
+    private val rankingComparator: Comparator<NotificationEntry> = Comparator { a, b ->
+        val na = a.sbn
+        val nb = b.sbn
+        val aRank = a.ranking.rank
+        val bRank = b.ranking.rank
+
+        val aMedia = isImportantMedia(a)
+        val bMedia = isImportantMedia(b)
+
+        val aSystemMax = a.isSystemMax()
+        val bSystemMax = b.isSystemMax()
+
+        val aHeadsUp = a.isRowHeadsUp
+        val bHeadsUp = b.isRowHeadsUp
+
+        if (usePeopleFiltering && a.isPeopleNotification() != b.isPeopleNotification()) {
+            if (a.isPeopleNotification()) -1 else 1
+        } else if (aHeadsUp != bHeadsUp) {
+            if (aHeadsUp) -1 else 1
+        } else if (aHeadsUp) {
+            // Provide consistent ranking with headsUpManager
+            headsUpManager.compare(a, b)
+        } else if (aMedia != bMedia) {
+            // Upsort current media notification.
+            if (aMedia) -1 else 1
+        } else if (aSystemMax != bSystemMax) {
+            // Upsort PRIORITY_MAX system notifications
+            if (aSystemMax) -1 else 1
+        } else if (a.isHighPriority != b.isHighPriority) {
+            -1 * java.lang.Boolean.compare(a.isHighPriority, b.isHighPriority)
+        } else if (aRank != bRank) {
+            aRank - bRank
+        } else {
+            nb.notification.`when`.compareTo(na.notification.`when`)
+        }
+    }
+
+    private fun isImportantMedia(entry: NotificationEntry): Boolean {
+        val importance = entry.ranking.importance
+        return entry.key == mediaManager.mediaNotificationKey && importance > IMPORTANCE_MIN
+    }
+
+    @VisibleForTesting
+    protected fun isHighPriority(entry: NotificationEntry): Boolean {
+        if (entry.importance >= IMPORTANCE_DEFAULT ||
+                hasHighPriorityCharacteristics(entry)) {
+            return true
+        }
+
+        if (groupManager.isSummaryOfGroup(entry.sbn)) {
+            val logicalChildren = groupManager.getLogicalChildren(entry.sbn)
+            for (child in logicalChildren) {
+                if (isHighPriority(child)) {
+                    return true
+                }
+            }
+        }
+
+        return false
+    }
+
+    private fun hasHighPriorityCharacteristics(entry: NotificationEntry): Boolean {
+        val c = entry.channel
+        val n = entry.sbn.notification
+
+        if (((n.isForegroundService && entry.ranking.importance >= IMPORTANCE_LOW) ||
+            n.hasMediaSession() ||
+            n.hasPerson() ||
+            n.hasStyle(Notification.MessagingStyle::class.java))) {
+            // Users who have long pressed and demoted to silent should not see the notification
+            // in the top section
+            if (c != null && c.hasUserSetImportance()) {
+                return false
+            }
+
+            return true
+        }
+
+        return false
+    }
+
+    fun updateRanking(
+        newRankingMap: RankingMap?,
+        entries: Collection<NotificationEntry>,
+        reason: String
+    ): List<NotificationEntry> {
+        val eSeq = entries.asSequence()
+
+        // TODO: may not be ideal to guard on null here, but this code is implementing exactly what
+        // NotificationData used to do
+        if (newRankingMap != null) {
+            rankingMap = newRankingMap
+            updateRankingForEntries(eSeq)
+        }
+
+        val filtered: Sequence<NotificationEntry>
+        synchronized(this) {
+            filtered = filterAndSortLocked(eSeq, reason)
+        }
+
+        return filtered.toList()
+    }
+
+    /** Uses the [rankingComparator] to sort notifications which aren't filtered */
+    private fun filterAndSortLocked(
+        entries: Sequence<NotificationEntry>,
+        reason: String
+    ): Sequence<NotificationEntry> {
+        notifLog.log(NotifEvent.FILTER_AND_SORT, reason)
+
+        return entries.filter { !notifFilter.shouldFilterOut(it) }
+                .sortedWith(rankingComparator)
+                .map {
+                    assignBucketForEntry(it)
+                    it
+                }
+    }
+
+    private fun assignBucketForEntry(entry: NotificationEntry) {
+        val isHeadsUp = entry.isRowHeadsUp
+        val isMedia = isImportantMedia(entry)
+        val isSystemMax = entry.isSystemMax()
+        setBucket(entry, isHeadsUp, isMedia, isSystemMax)
+    }
+
+    private fun setBucket(
+        entry: NotificationEntry,
+        isHeadsUp: Boolean,
+        isMedia: Boolean,
+        isSystemMax: Boolean
+    ) {
+        if (usePeopleFiltering && entry.hasAssociatedPeople()) {
+            entry.bucket = BUCKET_PEOPLE
+        } else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority) {
+            entry.bucket = BUCKET_ALERTING
+        } else {
+            entry.bucket = BUCKET_SILENT
+        }
+    }
+
+    private fun updateRankingForEntries(entries: Sequence<NotificationEntry>) {
+        rankingMap?.let { rankingMap ->
+            synchronized(entries) {
+                entries.forEach { entry ->
+                    val newRanking = Ranking()
+                    if (!rankingMap.getRanking(entry.key, newRanking)) {
+                        return@forEach
+                    }
+                    entry.ranking = newRanking
+
+                    val oldSbn = entry.sbn.cloneLight()
+                    val newOverrideGroupKey = newRanking.overrideGroupKey
+                    if (!Objects.equals(oldSbn.overrideGroupKey, newOverrideGroupKey)) {
+                        entry.sbn.overrideGroupKey = newOverrideGroupKey
+                        // TODO: notify group manager here?
+                        groupManager.onEntryUpdated(entry, oldSbn)
+                    }
+                    entry.setIsHighPriority(isHighPriority(entry))
+                }
+            }
+        }
+    }
+}
+
+// Convenience functions
+private fun NotificationEntry.isSystemMax(): Boolean {
+    return importance >= IMPORTANCE_HIGH && sbn.isSystemNotification()
+}
+
+private fun StatusBarNotification.isSystemNotification(): Boolean {
+    return "android" == packageName || "com.android.systemui" == packageName
+}
+
+private fun Notification.hasPerson(): Boolean {
+    val people: ArrayList<Person> =
+            (extras?.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST)) ?: ArrayList()
+    return people.isNotEmpty()
+}
+
+private fun Notification.hasStyle(targetStyleClass: Class<*>): Boolean {
+    return targetStyleClass == notificationStyle
+}
+
+private fun NotificationEntry.isPeopleNotification(): Boolean =
+        sbn.notification.hasStyle(Notification.MessagingStyle::class.java)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 52fd079..1c0a9d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -32,7 +32,6 @@
 import com.android.internal.util.NotificationMessagingUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.UiOffloadThread;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
@@ -61,7 +60,6 @@
             Dependency.get(NotificationGroupManager.class);
     private final NotificationGutsManager mGutsManager =
             Dependency.get(NotificationGutsManager.class);
-    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
     private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider =
             Dependency.get(NotificationInterruptionStateProvider.class);
 
@@ -81,16 +79,20 @@
     private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
     private BindRowCallback mBindRowCallback;
     private NotificationClicker mNotificationClicker;
-    private final NotificationLogger mNotificationLogger = Dependency.get(NotificationLogger.class);
+    private final NotificationLogger mNotificationLogger;
 
-    public NotificationRowBinderImpl(Context context, boolean allowLongPress,
+    public NotificationRowBinderImpl(
+            Context context,
+            boolean allowLongPress,
             KeyguardBypassController keyguardBypassController,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            NotificationLogger logger) {
         mContext = context;
         mMessagingUtil = new NotificationMessagingUtil(context);
         mAllowLongPress = allowLongPress;
         mKeyguardBypassController = keyguardBypassController;
         mStatusBarStateController = statusBarStateController;
+        mNotificationLogger = logger;
     }
 
     private NotificationRemoteInputManager getRemoteInputManager() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 90c5502..77ccf19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -43,9 +43,9 @@
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 import javax.inject.Inject;
@@ -113,7 +113,7 @@
         public void run() {
             mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
 
-            // 1. Loop over mNotificationData entries:
+            // 1. Loop over active entries:
             //   A. Keep list of visible notifications.
             //   B. Keep list of previously hidden, now visible notifications.
             // 2. Compute no-longer visible notifications by removing currently
@@ -121,8 +121,7 @@
             //    notifications.
             // 3. Report newly visible and no-longer visible notifications.
             // 4. Keep currently visible notifications for next report.
-            ArrayList<NotificationEntry> activeNotifications = mEntryManager
-                    .getNotificationData().getActiveNotifications();
+            List<NotificationEntry> activeNotifications = mEntryManager.getVisibleNotifications();
             int N = activeNotifications.size();
             for (int i = 0; i < N; i++) {
                 NotificationEntry entry = activeNotifications.get(i);
@@ -403,7 +402,7 @@
      */
     public void onExpansionChanged(String key, boolean isUserAction, boolean isExpanded) {
         NotificationVisibility.NotificationLocation location =
-                getNotificationLocation(mEntryManager.getNotificationData().get(key));
+                getNotificationLocation(mEntryManager.getActiveNotificationUnfiltered(key));
         mExpansionStateLogger.onExpansionChanged(key, isUserAction, isExpanded, location);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 0d8e30e..462fa59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -696,8 +696,7 @@
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateFooter() {
         boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL);
-        boolean showFooterView = (showDismissView ||
-                mEntryManager.getNotificationData().getActiveNotifications().size() != 0)
+        boolean showFooterView = (showDismissView || mEntryManager.hasActiveNotifications())
                 && mStatusBarState != StatusBarState.KEYGUARD
                 && !mRemoteInputManager.getController().isRemoteInputActive();
 
@@ -5787,11 +5786,6 @@
   }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public boolean hasActiveNotifications() {
-        return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
-    }
-
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateSpeedBumpIndex() {
         int speedBumpIndex = 0;
         int currentIndex = 0;
@@ -6400,7 +6394,7 @@
         @Override
         public boolean onDraggedDown(View startingChild, int dragLengthY) {
             if (mStatusBarState == StatusBarState.KEYGUARD
-                    && hasActiveNotifications()) {
+                    && mEntryManager.hasActiveNotifications()) {
                 mLockscreenGestureLogger.write(
                         MetricsEvent.ACTION_LS_SHADE,
                         (int) (dragLengthY / mDisplayMetrics.density),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
index 2c931ae..e763496 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
@@ -22,7 +22,7 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
+import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
 import javax.inject.Inject;
@@ -42,12 +42,12 @@
     public KeyguardEnvironmentImpl() {
     }
 
-    @Override  // NotificationData.KeyguardEnvironment
+    @Override  // NotificationEntryManager.KeyguardEnvironment
     public boolean isDeviceProvisioned() {
         return mDeviceProvisionedController.isDeviceProvisioned();
     }
 
-    @Override  // NotificationData.KeyguardEnvironment
+    @Override  // NotificationEntryManager.KeyguardEnvironment
     public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
         final int notificationUserId = n.getUserId();
         if (DEBUG && MULTIUSER_DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
index 93887a6..5703f06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
@@ -97,7 +97,7 @@
     }
 
     private boolean hasActiveNotifications() {
-        return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
+        return mEntryManager.hasActiveNotifications();
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 1e10b6f..3554b54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -15,7 +15,6 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
@@ -26,7 +25,6 @@
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -48,7 +46,6 @@
     private static final long AOD_ICONS_APPEAR_DURATION = 200;
 
     private final ContrastColorUtil mContrastColorUtil;
-    private final NotificationEntryManager mEntryManager;
     private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
     private final StatusBarStateController mStatusBarStateController;
     private final NotificationMediaManager mMediaManager;
@@ -91,7 +88,6 @@
         mStatusBar = statusBar;
         mContrastColorUtil = ContrastColorUtil.getInstance(context);
         mContext = context;
-        mEntryManager = Dependency.get(NotificationEntryManager.class);
         mStatusBarStateController = statusBarStateController;
         mStatusBarStateController.addCallback(this);
         mMediaManager = notificationMediaManager;
@@ -247,7 +243,7 @@
         if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
             return false;
         }
-        if (mEntryManager.getNotificationData().isAmbient(entry.getKey()) && !showAmbient) {
+        if (entry.getRanking().isAmbient() && !showAmbient) {
             return false;
         }
         if (hideCurrentMedia && entry.getKey().equals(mMediaManager.getMediaNotificationKey())) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6839fb4..6176cff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -3562,8 +3562,7 @@
 
     private void updateShowEmptyShadeView() {
         boolean showEmptyShadeView =
-                mBarState != StatusBarState.KEYGUARD &&
-                        mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
+                mBarState != StatusBarState.KEYGUARD && mEntryManager.hasActiveNotifications();
         showEmptyShadeView(showEmptyShadeView);
     }
 
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 0e1985d..adea8c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1228,7 +1228,8 @@
                         mContext,
                         mAllowNotificationLongPress,
                         mKeyguardBypassController,
-                        mStatusBarStateController);
+                        mStatusBarStateController,
+                        mNotificationLogger);
 
         mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
                 mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
@@ -2494,8 +2495,8 @@
         }
 
         if (DUMPTRUCK) {
-            synchronized (mEntryManager.getNotificationData()) {
-                mEntryManager.getNotificationData().dump(pw, "  ");
+            synchronized (mEntryManager) {
+                mEntryManager.dump(pw, "  ");
             }
 
             if (false) {
@@ -2753,11 +2754,7 @@
     };
 
     public void resetUserExpandedStates() {
-        ArrayList<NotificationEntry> activeNotifications = mEntryManager.getNotificationData()
-                .getActiveNotifications();
-        final int notificationCount = activeNotifications.size();
-        for (int i = 0; i < notificationCount; i++) {
-            NotificationEntry entry = activeNotifications.get(i);
+        for (NotificationEntry entry : mEntryManager.getVisibleNotifications()) {
             entry.resetUserExpansion();
         }
     }
@@ -2857,8 +2854,7 @@
         try {
             // consider the transition from peek to expanded to be a panel open,
             // but not one that clears notification effects.
-            int notificationLoad = mEntryManager.getNotificationData()
-                    .getActiveNotifications().size();
+            int notificationLoad = mEntryManager.getActiveNotificationsCount();
             mBarService.onPanelRevealed(false, notificationLoad);
         } catch (RemoteException ex) {
             // Won't fail unless the world has ended.
@@ -2876,8 +2872,7 @@
                     !mPresenter.isPresenterFullyCollapsed() &&
                             (mState == StatusBarState.SHADE
                                     || mState == StatusBarState.SHADE_LOCKED);
-            int notificationLoad = mEntryManager.getNotificationData().getActiveNotifications()
-                    .size();
+            int notificationLoad = mEntryManager.getActiveNotificationsCount();
             if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) {
                 notificationLoad = 1;
             }
@@ -3862,10 +3857,6 @@
         mScreenPinningRequest.showPrompt(taskId, allowCancel);
     }
 
-    public boolean hasActiveNotifications() {
-        return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
-    }
-
     @Override
     public void appTransitionCancelled(int displayId) {
         if (displayId == mDisplayId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 64a45e1..1cf43cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -326,12 +326,14 @@
             collapseOnMainThread();
         }
 
-        final int count =
-                mEntryManager.getNotificationData().getActiveNotifications().size();
-        final int rank = mEntryManager.getNotificationData().getRank(notificationKey);
+        //TODO(b/144306683): prove that this `activeEntry` is the same as `entry` above and simplify
+        // this call stack
+        NotificationEntry activeEntry =
+                mEntryManager.getActiveNotificationUnfiltered(notificationKey);
+        final int count = mEntryManager.getActiveNotificationsCount();
+        final int rank = activeEntry != null ? activeEntry.getRanking().getRank() : 0;
         NotificationVisibility.NotificationLocation location =
-                NotificationLogger.getNotificationLocation(
-                        mEntryManager.getNotificationData().get(notificationKey));
+                NotificationLogger.getNotificationLocation(activeEntry);
         final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
                 rank, count, true, location);
         try {
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 38ff862..30e26e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -75,7 +75,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
-import java.util.ArrayList;
+import java.util.List;
 
 public class StatusBarNotificationPresenter implements NotificationPresenter,
         ConfigurationController.ConfigurationListener,
@@ -252,8 +252,8 @@
     }
 
     private void updateNotificationOnUiModeChanged() {
-        ArrayList<NotificationEntry> userNotifications
-                = mEntryManager.getNotificationData().getNotificationsForCurrentUser();
+        List<NotificationEntry> userNotifications =
+                mEntryManager.getActiveNotificationsForCurrentUser();
         for (int i = 0; i < userNotifications.size(); i++) {
             NotificationEntry entry = userNotifications.get(i);
             ExpandableNotificationRow row = entry.getRow();
@@ -264,8 +264,8 @@
     }
 
     private void updateNotificationsOnDensityOrFontScaleChanged() {
-        ArrayList<NotificationEntry> userNotifications =
-                mEntryManager.getNotificationData().getNotificationsForCurrentUser();
+        List<NotificationEntry> userNotifications =
+                mEntryManager.getActiveNotificationsForCurrentUser();
         for (int i = 0; i < userNotifications.size(); i++) {
             NotificationEntry entry = userNotifications.get(i);
             entry.onDensityOrFontScaleChanged();
@@ -326,7 +326,7 @@
     }
 
     public boolean hasActiveNotifications() {
-        return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
+        return mEntryManager.hasActiveNotifications();
     }
 
     public boolean canHeadsUp(NotificationEntry entry, StatusBarNotification sbn) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index e63b6d66..02a3766 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -102,7 +102,7 @@
     public void testAppOps_appOpAddedToForegroundNotif() {
         // GIVEN a notification associated with a foreground service
         NotificationEntry entry = addFgEntry();
-        when(mEntryManager.getPendingOrCurrentNotif(entry.getKey())).thenReturn(entry);
+        when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry);
 
         // WHEN we are notified of a new app op for this notification
         mFsc.onAppOpChanged(
@@ -123,7 +123,7 @@
         // GIVEN a foreground service associated notification that already has the correct app op
         NotificationEntry entry = addFgEntry();
         entry.mActiveAppOps.add(AppOpsManager.OP_CAMERA);
-        when(mEntryManager.getPendingOrCurrentNotif(entry.getKey())).thenReturn(entry);
+        when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry);
 
         // WHEN we are notified of the same app op for this notification
         mFsc.onAppOpChanged(
@@ -143,7 +143,7 @@
     public void testAppOps_appOpNotAddedToUnrelatedNotif() {
         // GIVEN no notification entries correspond to the newly updated appOp
         NotificationEntry entry = addFgEntry();
-        when(mEntryManager.getPendingOrCurrentNotif(entry.getKey())).thenReturn(null);
+        when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(null);
 
         // WHEN a new app op is detected
         mFsc.onAppOpChanged(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index a7c0204..8c9f759 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -72,7 +72,6 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationFilter;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.DozeParameters;
@@ -141,8 +140,6 @@
     private ExpandableNotificationRow mNonBubbleNotifRow;
 
     @Mock
-    private NotificationData mNotificationData;
-    @Mock
     private BubbleController.BubbleStateChangeListener mBubbleStateChangeListener;
     @Mock
     private BubbleController.BubbleExpandListener mBubbleExpandListener;
@@ -183,10 +180,9 @@
         mNonBubbleNotifRow = mNotificationTestHelper.createRow();
 
         // Return non-null notification data from the NEM
-        when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
-        when(mNotificationData.get(mRow.getEntry().getKey())).thenReturn(mRow.getEntry());
-        when(mNotificationData.getChannel(mRow.getEntry().getKey())).thenReturn(
-                mRow.getEntry().getChannel());
+        when(mNotificationEntryManager
+                .getActiveNotificationUnfiltered(mRow.getEntry().getKey())).thenReturn(
+                mRow.getEntry());
 
         mZenModeConfig.suppressedVisualEffects = 0;
         when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index 86869bd..2f53a01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -37,7 +37,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -54,7 +53,6 @@
 
     @Mock private NotificationPresenter mPresenter;
     @Mock private NotificationListenerService.RankingMap mRanking;
-    @Mock private NotificationData mNotificationData;
 
     // Dependency mocks:
     @Mock private NotificationEntryManager mEntryManager;
@@ -74,8 +72,6 @@
                 new Handler(TestableLooper.get(this).getLooper()));
         mContext.addMockSystemService(NotificationManager.class, mNotificationManager);
 
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
-
         mListener = new NotificationListener(mContext);
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
@@ -90,7 +86,7 @@
 
     @Test
     public void testNotificationUpdateCallsUpdateNotification() {
-        when(mNotificationData.get(mSbn.getKey()))
+        when(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()))
                 .thenReturn(
                         new NotificationEntryBuilder()
                                 .setSbn(mSbn)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 548f7a8..d54e24ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.content.Intent.ACTION_USER_SWITCHED;
 import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 
@@ -24,7 +25,6 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -49,7 +49,6 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -72,7 +71,6 @@
 
     // Dependency mocks:
     @Mock private NotificationEntryManager mEntryManager;
-    @Mock private NotificationData mNotificationData;
     @Mock private DeviceProvisionedController mDeviceProvisionedController;
     @Mock private StatusBarKeyguardViewManager mKeyguardViewManager;
     @Mock private BroadcastDispatcher mBroadcastDispatcher;
@@ -93,7 +91,6 @@
 
         when(mUserManager.getProfiles(mCurrentUserId)).thenReturn(Lists.newArrayList(
                 new UserInfo(mCurrentUserId, "", 0), new UserInfo(mCurrentUserId + 1, "", 0)));
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 Handler.createAsync(Looper.myLooper()));
 
@@ -170,9 +167,10 @@
                 NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1);
-        when(mNotificationData.isHighPriority(any())).thenReturn(false);
 
-        NotificationEntry entry = new NotificationEntryBuilder().build();
+        NotificationEntry entry = new NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_LOW)
+                .build();
         entry.setBucket(BUCKET_SILENT);
 
         assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(entry));
@@ -186,10 +184,12 @@
                 NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
-        when(mNotificationData.isHighPriority(any())).thenReturn(false);
 
-        NotificationEntry entry = new NotificationEntryBuilder().build();
+        NotificationEntry entry = new NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_LOW)
+                .build();
         entry.setBucket(BUCKET_SILENT);
+        entry.setIsHighPriority(true);
         assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(entry));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 90bd0e9..88546b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -26,7 +26,6 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.Instrumentation;
 import android.app.Notification;
 import android.app.Notification.BubbleMetadata;
 import android.app.NotificationChannel;
@@ -40,8 +39,6 @@
 import android.view.LayoutInflater;
 import android.widget.RemoteViews;
 
-import androidx.test.InstrumentationRegistry;
-
 import com.android.systemui.TestableDependency;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.bubbles.BubblesTestActivity;
@@ -72,7 +69,6 @@
     private static final String GROUP_KEY = "gruKey";
 
     private final Context mContext;
-    private final Instrumentation mInstrumentation;
     private int mId;
     private final NotificationGroupManager mGroupManager;
     private ExpandableNotificationRow mRow;
@@ -83,7 +79,7 @@
         dependency.injectMockDependency(NotificationMediaManager.class);
         dependency.injectMockDependency(BubbleController.class);
         dependency.injectMockDependency(StatusBarWindowController.class);
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        dependency.injectMockDependency(SmartReplyController.class);
         StatusBarStateController stateController = mock(StatusBarStateController.class);
         mGroupManager = new NotificationGroupManager(stateController);
         mHeadsUpManager = new HeadsUpManagerPhone(mContext, stateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 18649bf..99c94ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -46,7 +46,6 @@
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -73,7 +72,6 @@
 @TestableLooper.RunWithLooper
 public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
     @Mock private NotificationPresenter mPresenter;
-    @Mock private NotificationData mNotificationData;
     @Spy private FakeListContainer mListContainer = new FakeListContainer();
 
     // Dependency mocks:
@@ -105,8 +103,6 @@
 
         mHelper = new NotificationTestHelper(mContext, mDependency);
 
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
-
         mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
                 mHandler, mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
                 mock(StatusBarStateControllerImpl.class), mEntryManager,
@@ -139,7 +135,7 @@
         mListContainer.addContainerView(entry0.getRow());
         mListContainer.addContainerView(entry1.getRow());
         mListContainer.addContainerView(entry2.getRow());
-        when(mNotificationData.getActiveNotifications()).thenReturn(
+        when(mEntryManager.getVisibleNotifications()).thenReturn(
                 Lists.newArrayList(entry0, entry1, entry2));
 
         // Set up group manager to report that they should be bundled now.
@@ -168,7 +164,7 @@
 
         // Set up the prior state to look like one top level notification.
         mListContainer.addContainerView(entry0.getRow());
-        when(mNotificationData.getActiveNotifications()).thenReturn(
+        when(mEntryManager.getVisibleNotifications()).thenReturn(
                 Lists.newArrayList(entry0, entry1, entry2));
 
         // Set up group manager to report that they should not be bundled now.
@@ -197,7 +193,7 @@
 
         // Set up the prior state to look like a top level notification.
         mListContainer.addContainerView(entry0.getRow());
-        when(mNotificationData.getActiveNotifications()).thenReturn(
+        when(mEntryManager.getVisibleNotifications()).thenReturn(
                 Lists.newArrayList(entry0, entry1));
 
         // Set up group manager to report a suppressed summary now.
@@ -219,7 +215,7 @@
     public void testUpdateNotificationViews_appOps() throws Exception {
         NotificationEntry entry0 = createEntry();
         entry0.setRow(spy(entry0.getRow()));
-        when(mNotificationData.getActiveNotifications()).thenReturn(
+        when(mEntryManager.getVisibleNotifications()).thenReturn(
                 Lists.newArrayList(entry0));
         mListContainer.addContainerView(entry0.getRow());
 
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 86ef6e8..a98945f 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
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.service.notification.NotificationListenerService.REASON_CANCEL;
 
 import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
@@ -28,7 +29,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
@@ -40,14 +40,15 @@
 
 import android.app.ActivityManager;
 import android.app.Notification;
-import android.app.NotificationManager;
+import android.app.NotificationChannel;
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
-import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -73,18 +74,18 @@
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationRemoveInterceptor;
+import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
-import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
+import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.row.RowInflaterTask;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -93,6 +94,7 @@
 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.Assert;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -104,13 +106,14 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper()
 public class NotificationEntryManagerTest extends SysuiTestCase {
     private static final String TEST_PACKAGE_NAME = "test";
     private static final int TEST_UID = 0;
@@ -123,7 +126,7 @@
     @Mock private NotificationRemoveInterceptor mRemoveInterceptor;
     @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
     @Mock private HeadsUpManager mHeadsUpManager;
-    @Mock private NotificationListenerService.RankingMap mRankingMap;
+    @Mock private RankingMap mRankingMap;
     @Mock private RemoteInputController mRemoteInputController;
 
     // Dependency mocks:
@@ -139,6 +142,7 @@
     @Mock private SmartReplyController mSmartReplyController;
     @Mock private RowInflaterTask mAsyncInflationTask;
     @Mock private NotificationRowBinder mMockedRowBinder;
+    @Mock private NotifLog mNotifLog;
 
     private int mId;
     private NotificationEntry mEntry;
@@ -146,43 +150,9 @@
     private TestableNotificationEntryManager mEntryManager;
     private CountDownLatch mCountDownLatch;
 
-    private class TestableNotificationEntryManager extends NotificationEntryManager {
-        private final CountDownLatch mCountDownLatch;
-
-        TestableNotificationEntryManager() {
-            super(
-                    new NotificationData(
-                            mock(NotificationSectionsFeatureManager.class),
-                            mock(NotifLog.class),
-                            mock(PeopleNotificationIdentifier.class)),
-                    mock(NotifLog.class));
-            mCountDownLatch = new CountDownLatch(1);
-        }
-
-        public void setNotificationData(NotificationData data) {
-            mNotificationData = data;
-        }
-
-        @Override
-        public void onAsyncInflationFinished(NotificationEntry entry,
-                @InflationFlag int inflatedFlags) {
-            super.onAsyncInflationFinished(entry, inflatedFlags);
-
-            mCountDownLatch.countDown();
-        }
-
-        public CountDownLatch getCountDownLatch() {
-            return mCountDownLatch;
-        }
-
-        public ArrayList<NotificationLifetimeExtender> getLifetimeExtenders() {
-            return mNotificationLifetimeExtenders;
-        }
-    }
-
     private void setUserSentiment(String key, int sentiment) {
         doAnswer(invocationOnMock -> {
-            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
+            Ranking ranking = (Ranking)
                     invocationOnMock.getArguments()[1];
             ranking.populate(
                     key,
@@ -190,16 +160,16 @@
                     false,
                     0,
                     0,
-                    NotificationManager.IMPORTANCE_DEFAULT,
+                    IMPORTANCE_DEFAULT,
                     null, null,
                     null, null, null, true, sentiment, false, -1, false, null, null, false, false);
             return true;
-        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
+        }).when(mRankingMap).getRanking(eq(key), any(Ranking.class));
     }
 
     private void setSmartActions(String key, ArrayList<Notification.Action> smartActions) {
         doAnswer(invocationOnMock -> {
-            NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
+            Ranking ranking = (Ranking)
                     invocationOnMock.getArguments()[1];
             ranking.populate(
                     key,
@@ -207,13 +177,13 @@
                     false,
                     0,
                     0,
-                    NotificationManager.IMPORTANCE_DEFAULT,
+                    IMPORTANCE_DEFAULT,
                     null, null,
                     null, null, null, true,
-                    NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false, -1,
+                    Ranking.USER_SENTIMENT_NEUTRAL, false, -1,
                     false, smartActions, null, false, false);
             return true;
-        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
+        }).when(mRankingMap).getRanking(eq(key), any(Ranking.class));
     }
 
     @Before
@@ -249,7 +219,18 @@
 
         mEntry.expandedIcon = mock(StatusBarIconView.class);
 
-        mEntryManager = new TestableNotificationEntryManager();
+        mEntryManager = new TestableNotificationEntryManager(
+                mNotifLog,
+                mGroupManager,
+                new NotificationRankingManager(
+                        () -> mock(NotificationMediaManager.class),
+                        mGroupManager,
+                        mHeadsUpManager,
+                        mock(NotificationFilter.class),
+                        mNotifLog,
+                        mock(NotificationSectionsFeatureManager.class)),
+                mEnvironment
+        );
         Dependency.get(InitController.class).executePostInitTasks();
         mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
         mEntryManager.addNotificationEntryListener(mEntryListener);
@@ -258,19 +239,19 @@
         NotificationRowBinderImpl notificationRowBinder =
                 new NotificationRowBinderImpl(mContext, true, /* allowLongPress */
                         mock(KeyguardBypassController.class),
-                        mock(StatusBarStateController.class));
+                        mock(StatusBarStateController.class),
+                        mock(NotificationLogger.class));
         notificationRowBinder.setUpWithPresenter(
                 mPresenter, mListContainer, mHeadsUpManager, mEntryManager, mBindCallback);
         notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
         mEntryManager.setRowBinder(notificationRowBinder);
 
         setUserSentiment(
-                mEntry.getKey(), NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
+                mEntry.getKey(), Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
     @Test
     public void testAddNotification() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
         TestableLooper.get(this).processAllMessages();
 
         doAnswer(invocation -> {
@@ -299,21 +280,20 @@
         verify(mEntryListener).onNotificationAdded(entry);
         verify(mPresenter).updateNotificationViews();
 
-        assertEquals(mEntryManager.getNotificationData().get(mSbn.getKey()), entry);
+        assertEquals(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()), entry);
         assertNotNull(entry.getRow());
         assertEquals(mEntry.getUserSentiment(),
-                NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
+                Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
     @Test
     public void testUpdateNotification() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
         TestableLooper.get(this).processAllMessages();
 
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
 
         setUserSentiment(
-                mEntry.getKey(), NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+                mEntry.getKey(), Ranking.USER_SENTIMENT_NEGATIVE);
 
         mEntryManager.updateNotification(mSbn, mRankingMap);
         TestableLooper.get(this).processMessages(1);
@@ -327,19 +307,15 @@
         verify(mEntryListener).onPostEntryUpdated(mEntry);
 
         assertNotNull(mEntry.getRow());
-        assertEquals(mEntry.getUserSentiment(),
-                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE,
+                mEntry.getUserSentiment());
     }
 
     @Test
     public void testUpdateNotification_prePostEntryOrder() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
         TestableLooper.get(this).processAllMessages();
 
-        NotificationData notifData = mock(NotificationData.class);
-        when(notifData.get(mEntry.getKey())).thenReturn(mEntry);
-
-        mEntryManager.setNotificationData(notifData);
+        mEntryManager.addActiveNotificationForTest(mEntry);
 
         mEntryManager.updateNotification(mSbn, mRankingMap);
         TestableLooper.get(this).processMessages(1);
@@ -349,9 +325,8 @@
         verify(mEntryListener, never()).onInflationError(any(), any());
 
         // Ensure that update callbacks happen in correct order
-        InOrder order = inOrder(mEntryListener, notifData, mPresenter, mEntryListener);
+        InOrder order = inOrder(mEntryListener, mPresenter, mEntryListener);
         order.verify(mEntryListener).onPreEntryUpdated(mEntry);
-        order.verify(notifData).filterAndSort(anyString());
         order.verify(mPresenter).updateNotificationViews();
         order.verify(mEntryListener).onPostEntryUpdated(mEntry);
 
@@ -359,11 +334,12 @@
     }
 
     @Test
-    public void testRemoveNotification() throws Exception {
-        com.android.systemui.util.Assert.isNotMainThread();
+    public void testRemoveNotification() {
+        // Row inflation happens off thread, so pretend that this test looper is main
+        Assert.sMainLooper = TestableLooper.get(this).getLooper();
 
         mEntry.setRow(mRow);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
 
         mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
@@ -374,12 +350,11 @@
                 eq(mEntry), any(), eq(false) /* removedByUser */);
         verify(mRow).setRemoved();
 
-        assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
+        assertNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
     }
 
     @Test
     public void testRemoveNotification_onEntryRemoveNotFiredIfEntryDoesntExist() {
-        com.android.systemui.util.Assert.isNotMainThread();
 
         mEntryManager.removeNotification("not_a_real_key", mRankingMap, UNDEFINED_DISMISS_REASON);
 
@@ -388,8 +363,7 @@
     }
 
     @Test
-    public void testRemoveNotification_whilePending() throws InterruptedException {
-        com.android.systemui.util.Assert.isNotMainThread();
+    public void testRemoveNotification_whilePending() {
 
         mEntryManager.setRowBinder(mMockedRowBinder);
 
@@ -408,7 +382,7 @@
 
         mEntry.setRow(mRow);
         mEntry.setInflationTask(mAsyncInflationTask);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
         setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
@@ -424,7 +398,7 @@
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
 
         mEntry.setRow(mRow);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
         setSmartActions(mEntry.getKey(), null);
 
         mEntryManager.updateNotificationRanking(mRankingMap);
@@ -438,7 +412,7 @@
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
 
         mEntry.setRow(null);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
         setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
@@ -466,7 +440,7 @@
     public void testLifetimeExtenders_ifNotificationIsRetainedItIsntRemoved() {
         // GIVEN an entry manager with a notification
         mEntryManager.setRowBinder(mMockedRowBinder);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
 
         // GIVEN a lifetime extender that always tries to extend lifetime
         NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class);
@@ -479,15 +453,18 @@
         // THEN the extender is asked to manage the lifetime
         verify(extender).setShouldManageLifetime(mEntry, true);
         // THEN the notification is retained
-        assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
+        assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
         verify(mEntryListener, never()).onEntryRemoved(eq(mEntry), any(), eq(false));
     }
 
     @Test
     public void testLifetimeExtenders_whenRetentionEndsNotificationIsRemoved() {
+        // Row inflation happens off thread, so pretend that this test looper is main
+        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+
         // GIVEN an entry manager with a notification whose life has been extended
         mEntryManager.setRowBinder(mMockedRowBinder);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
         final FakeNotificationLifetimeExtender extender = new FakeNotificationLifetimeExtender();
         mEntryManager.addNotificationLifetimeExtender(extender);
         mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
@@ -498,7 +475,7 @@
         extender.getCallback().onSafeToRemove(mEntry.getKey());
 
         // THEN the notification is removed
-        assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
+        assertNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
         verify(mEntryListener).onEntryRemoved(eq(mEntry), any(), eq(false));
     }
 
@@ -506,7 +483,7 @@
     public void testLifetimeExtenders_whenNotificationUpdatedRetainersAreCanceled() {
         // GIVEN an entry manager with a notification whose life has been extended
         mEntryManager.setRowBinder(mMockedRowBinder);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
         NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class);
         when(extender.shouldExtendLifetime(mEntry)).thenReturn(true);
         mEntryManager.addNotificationLifetimeExtender(extender);
@@ -523,7 +500,7 @@
     public void testLifetimeExtenders_whenNewExtenderTakesPrecedenceOldExtenderIsCanceled() {
         // GIVEN an entry manager with a notification
         mEntryManager.setRowBinder(mMockedRowBinder);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
 
         // GIVEN two lifetime extenders, the first which never extends and the second which
         // always extends
@@ -554,15 +531,15 @@
      */
     @Test
     public void testPerformRemoveNotification_removedEntry() {
-        mEntryManager.getNotificationData().remove(mSbn.getKey(), null /* ranking */);
+        mEntryManager.removeNotification(mSbn.getKey(), null, 0);
         mEntryManager.performRemoveNotification(mSbn, REASON_CANCEL);
     }
 
     @Test
-    public void testRemoveInterceptor_interceptsDontGetRemoved() {
+    public void testRemoveInterceptor_interceptsDontGetRemoved() throws InterruptedException {
         // GIVEN an entry manager with a notification
         mEntryManager.setRowBinder(mMockedRowBinder);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
 
         // GIVEN interceptor that intercepts that entry
         when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.getKey()), anyInt()))
@@ -572,16 +549,19 @@
         mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the interceptor intercepts & the entry is not removed & no listeners are called
-        assertNotNull(mEntryManager.getNotificationData().get(mEntry.getKey()));
+        assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
         verify(mEntryListener, never()).onEntryRemoved(eq(mEntry),
                 any(NotificationVisibility.class), anyBoolean());
     }
 
     @Test
     public void testRemoveInterceptor_notInterceptedGetsRemoved() {
+        // Row inflation happens off thread, so pretend that this test looper is main
+        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+
         // GIVEN an entry manager with a notification
         mEntryManager.setRowBinder(mMockedRowBinder);
-        mEntryManager.getNotificationData().add(mEntry);
+        mEntryManager.addActiveNotificationForTest(mEntry);
 
         // GIVEN interceptor that doesn't intercept
         when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.getKey()), anyInt()))
@@ -591,7 +571,7 @@
         mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the interceptor intercepts & the entry is not removed & no listeners are called
-        assertNull(mEntryManager.getNotificationData().get(mEntry.getKey()));
+        assertNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
         verify(mEntryListener, atLeastOnce()).onEntryRemoved(eq(mEntry),
                 any(NotificationVisibility.class), anyBoolean());
     }
@@ -612,6 +592,63 @@
                 .build();
     }
 
+    /* Tests annexed from NotificationDataTest go here */
+
+    @Test
+    public void testChannelIsSetWhenAdded() {
+        NotificationChannel nc = new NotificationChannel(
+                "testId",
+                "testName",
+                IMPORTANCE_DEFAULT);
+
+        Ranking r = new RankingBuilder()
+                .setKey(mEntry.getKey())
+                .setChannel(nc)
+                .build();
+
+        RankingMap rm = new RankingMap(new Ranking[] { r });
+
+        // GIVEN: a notification is added, and the ranking updated
+        mEntryManager.addActiveNotificationForTest(mEntry);
+        mEntryManager.updateRanking(rm, "testReason");
+
+        // THEN the notification entry better have a channel on it
+        assertEquals(
+                "Channel must be set when adding a notification",
+                nc.getName(),
+                mEntry.getChannel().getName());
+    }
+
+    @Test
+    public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications() {
+        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+
+        NotificationEntry e2 = new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_NAME)
+                .setOpPkg(TEST_PACKAGE_NAME)
+                .setUid(TEST_UID)
+                .setId(mId++)
+                .setNotification(n.build())
+                .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+                .build();
+
+        mEntryManager.addActiveNotificationForTest(mEntry);
+        mEntryManager.addActiveNotificationForTest(e2);
+
+        when(mEnvironment.isNotificationForCurrentProfiles(mEntry.getSbn())).thenReturn(false);
+        when(mEnvironment.isNotificationForCurrentProfiles(e2.getSbn())).thenReturn(true);
+
+        List<NotificationEntry> result = mEntryManager.getActiveNotificationsForCurrentUser();
+        assertEquals(result.size(), 1);
+        junit.framework.Assert.assertEquals(result.get(0), e2);
+    }
+
+    /* End annex */
+
     private Notification.Action createAction() {
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index d85f275..68730d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -44,7 +44,7 @@
 import com.android.systemui.statusbar.NotificationEntryBuilder;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -71,7 +71,7 @@
     @Mock
     ForegroundServiceController mFsc;
     @Mock
-    NotificationData.KeyguardEnvironment mEnvironment;
+    KeyguardEnvironment mEnvironment;
     private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
 
     private NotificationFilter mNotificationFilter;
@@ -96,7 +96,7 @@
                 new NotificationGroupManager(mock(StatusBarStateController.class)));
         mDependency.injectMockDependency(ShadeController.class);
         mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
-        mDependency.injectTestDependency(NotificationData.KeyguardEnvironment.class, mEnvironment);
+        mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
         when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
         mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
index cc56949..133d52b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
@@ -17,9 +17,7 @@
 package com.android.systemui.statusbar.notification;
 
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
 import android.app.Notification;
@@ -34,14 +32,10 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-import com.android.systemui.util.DeviceConfigProxyFake;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -67,13 +61,6 @@
     private NotificationEntryListener mEntryListener;
     private DeviceProvisionedListener mProvisionedListener;
 
-    // TODO: Remove this once EntryManager no longer needs to be mocked
-    private NotificationData mNotificationData =
-            new NotificationData(
-                    new NotificationSectionsFeatureManager(new DeviceConfigProxyFake(), mContext),
-                    mock(NotifLog.class),
-                    mock(PeopleNotificationIdentifier.class));
-
     private int mNextNotifId = 0;
 
     @Before
@@ -81,8 +68,6 @@
         MockitoAnnotations.initMocks(this);
         mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
 
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
-
         mController = new NotificationListController(
                 mEntryManager,
                 mListContainer,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
new file mode 100644
index 0000000..34beefe
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
@@ -0,0 +1,58 @@
+/*
+ * 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.notification
+
+import com.android.systemui.statusbar.NotificationPresenter
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
+import com.android.systemui.statusbar.notification.logging.NotifLog
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.phone.NotificationGroupManager
+
+import java.util.concurrent.CountDownLatch
+
+/**
+ * Enable some test capabilities for NEM without making everything public on the base class
+ */
+class TestableNotificationEntryManager(
+    log: NotifLog,
+    gm: NotificationGroupManager,
+    rm: NotificationRankingManager,
+    ke: KeyguardEnvironment
+) : NotificationEntryManager(log, gm, rm, ke) {
+
+    public var countDownLatch: CountDownLatch = CountDownLatch(1)
+
+    override fun onAsyncInflationFinished(entry: NotificationEntry?, inflatedFlags: Int) {
+        super.onAsyncInflationFinished(entry, inflatedFlags)
+        countDownLatch.countDown()
+    }
+
+    fun setUpForTest(
+        presenter: NotificationPresenter?,
+        listContainer: NotificationListContainer?,
+        headsUpManager: HeadsUpManagerPhone?
+    ) {
+        super.setUpWithPresenter(presenter, listContainer, headsUpManager)
+    }
+
+    fun setActiveNotificationList(activeList: List<NotificationEntry>) {
+        mSortedAndFiltered.clear()
+        mSortedAndFiltered.addAll(activeList)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
deleted file mode 100644
index 1a469d8..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
- * Copyright (C) 2017 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.collection;
-
-import static android.app.Notification.CATEGORY_ALARM;
-import static android.app.Notification.CATEGORY_CALL;
-import static android.app.Notification.CATEGORY_EVENT;
-import static android.app.Notification.CATEGORY_MESSAGE;
-import static android.app.Notification.CATEGORY_REMINDER;
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-
-import static com.android.systemui.statusbar.NotificationEntryHelper.modifySbn;
-import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_CHANNEL;
-import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_IMPORTANCE;
-import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_RANK;
-import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_VIS_EFFECTS;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Person;
-import android.content.Intent;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Icon;
-import android.media.session.MediaSession;
-import android.os.Bundle;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationListenerService.Ranking;
-import android.service.notification.SnoozeCriterion;
-import android.service.notification.StatusBarNotification;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.InitController;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationEntryBuilder;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.SbnBuilder;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ShadeController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public class NotificationDataTest extends SysuiTestCase {
-
-    private static final int UID_NORMAL = 123;
-    private static final int UID_ALLOW_DURING_SETUP = 456;
-    private static final NotificationChannel NOTIFICATION_CHANNEL =
-            new NotificationChannel("id", "name", NotificationChannel.USER_LOCKED_IMPORTANCE);
-
-    private NotificationEntry mEntry;
-
-    @Mock
-    ForegroundServiceController mFsc;
-    @Mock
-    NotificationData.KeyguardEnvironment mEnvironment;
-
-    private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
-    private TestableNotificationData mNotificationData;
-    private ExpandableNotificationRow mRow;
-
-    @Before
-    public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        MockitoAnnotations.initMocks(this);
-
-        mEntry = new NotificationEntryBuilder()
-                .setUid(UID_NORMAL)
-                .build();
-
-        when(mMockPackageManager.checkUidPermission(
-                eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
-                eq(UID_NORMAL)))
-                .thenReturn(PackageManager.PERMISSION_DENIED);
-        when(mMockPackageManager.checkUidPermission(
-                eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
-                eq(UID_ALLOW_DURING_SETUP)))
-                .thenReturn(PackageManager.PERMISSION_GRANTED);
-
-        mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
-        mDependency.injectTestDependency(NotificationGroupManager.class,
-                new NotificationGroupManager(mock(StatusBarStateController.class)));
-        mDependency.injectMockDependency(ShadeController.class);
-        mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
-        mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
-        when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
-        when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
-        mNotificationData = new TestableNotificationData(
-                mock(NotificationSectionsFeatureManager.class));
-        mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class), "");
-        mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
-        Dependency.get(InitController.class).executePostInitTasks();
-    }
-
-    @Test
-    public void testChannelSetWhenAdded() {
-        Bundle override = new Bundle();
-        override.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
-        mNotificationData.rankingOverrides.put(mRow.getEntry().getKey(), override);
-        mNotificationData.add(mRow.getEntry());
-        assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().getChannel());
-    }
-
-    @Test
-    public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications()
-            throws Exception {
-        mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
-                .createRow();
-        mNotificationData.add(row2.getEntry());
-
-        when(mEnvironment.isNotificationForCurrentProfiles(
-                mRow.getEntry().getSbn())).thenReturn(false);
-        when(mEnvironment.isNotificationForCurrentProfiles(
-                row2.getEntry().getSbn())).thenReturn(true);
-        ArrayList<NotificationEntry> result =
-                mNotificationData.getNotificationsForCurrentUser();
-
-        assertEquals(result.size(), 1);
-        junit.framework.Assert.assertEquals(result.get(0), row2.getEntry());
-    }
-
-    @Test
-    public void testIsExemptFromDndVisualSuppression_foreground() {
-        initStatusBarNotification(false);
-
-        mEntry.getSbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
-        mEntry.setRow(mRow);
-        mNotificationData.add(mEntry);
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
-
-        assertTrue(mEntry.isExemptFromDndVisualSuppression());
-        assertFalse(mEntry.shouldSuppressAmbient());
-    }
-
-    @Test
-    public void testIsExemptFromDndVisualSuppression_media() {
-        initStatusBarNotification(false);
-        Notification n = mEntry.getSbn().getNotification();
-        Notification.Builder nb = Notification.Builder.recoverBuilder(mContext, n);
-        nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
-        n = nb.build();
-        modifySbn(mEntry)
-                .setNotification(n)
-                .build();
-        mEntry.setRow(mRow);
-        mNotificationData.add(mEntry);
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
-
-        assertTrue(mEntry.isExemptFromDndVisualSuppression());
-        assertFalse(mEntry.shouldSuppressAmbient());
-    }
-
-    @Test
-    public void testIsExemptFromDndVisualSuppression_system() {
-        initStatusBarNotification(false);
-        mEntry.setRow(mRow);
-        mEntry.mIsSystemNotification = true;
-        mNotificationData.add(mEntry);
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
-
-        assertTrue(mEntry.isExemptFromDndVisualSuppression());
-        assertFalse(mEntry.shouldSuppressAmbient());
-    }
-
-    @Test
-    public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
-        initStatusBarNotification(false);
-        NotificationEntry entry = new NotificationEntryBuilder()
-                .setUid(UID_NORMAL)
-                .build();
-        entry.setRow(mRow);
-        entry.mIsSystemNotification = true;
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_VIS_EFFECTS, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
-        mNotificationData.rankingOverrides.put(entry.getKey(), override);
-        mNotificationData.add(entry);
-
-        modifySbn(entry)
-                .setNotification(
-                        new Notification.Builder(mContext, "").setCategory(CATEGORY_CALL).build())
-                .build();
-        assertFalse(entry.isExemptFromDndVisualSuppression());
-        assertTrue(entry.shouldSuppressAmbient());
-
-        modifySbn(entry)
-                .setNotification(
-                        new Notification.Builder(mContext, "")
-                                .setCategory(CATEGORY_REMINDER)
-                                .build())
-                .build();
-        assertFalse(entry.isExemptFromDndVisualSuppression());
-
-        modifySbn(entry)
-                .setNotification(
-                        new Notification.Builder(mContext, "").setCategory(CATEGORY_ALARM).build())
-                .build();
-        assertFalse(entry.isExemptFromDndVisualSuppression());
-
-        modifySbn(entry)
-                .setNotification(
-                        new Notification.Builder(mContext, "").setCategory(CATEGORY_EVENT).build())
-                .build();
-        assertFalse(entry.isExemptFromDndVisualSuppression());
-
-        modifySbn(entry)
-                .setNotification(
-                        new Notification.Builder(mContext, "")
-                                .setCategory(CATEGORY_MESSAGE)
-                                .build())
-                .build();
-        assertFalse(entry.isExemptFromDndVisualSuppression());
-    }
-
-    @Test
-    public void testCreateNotificationDataEntry_RankingUpdate() {
-        StatusBarNotification sbn = new SbnBuilder().build();
-        sbn.getNotification().actions =
-                new Notification.Action[] { createContextualAction("appGeneratedAction") };
-
-        ArrayList<Notification.Action> systemGeneratedSmartActions =
-                createActions("systemGeneratedAction");
-
-        SnoozeCriterion snoozeCriterion = new SnoozeCriterion("id", "explanation", "confirmation");
-        ArrayList<SnoozeCriterion> snoozeCriterions = new ArrayList<>();
-        snoozeCriterions.add(snoozeCriterion);
-
-        Ranking ranking = new RankingBuilder()
-                .setKey(sbn.getKey())
-                .setSmartActions(systemGeneratedSmartActions)
-                .setChannel(NOTIFICATION_CHANNEL)
-                .setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
-                .setSnoozeCriteria(snoozeCriterions)
-                .build();
-
-        NotificationEntry entry =
-                new NotificationEntry(sbn, ranking);
-
-        assertEquals(systemGeneratedSmartActions, entry.getSmartActions());
-        assertEquals(NOTIFICATION_CHANNEL, entry.getChannel());
-        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.getUserSentiment());
-        assertEquals(snoozeCriterions, entry.getSnoozeCriteria());
-    }
-
-    @Test
-    public void notificationDataEntry_testIsLastMessageFromReply() {
-        Person.Builder person = new Person.Builder()
-                .setName("name")
-                .setKey("abc")
-                .setUri("uri")
-                .setBot(true);
-
-        // EXTRA_MESSAGING_PERSON is the same Person as the sender in last message in EXTRA_MESSAGES
-        Bundle bundle = new Bundle();
-        bundle.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person.build());
-        Bundle[] messagesBundle = new Bundle[]{ new Notification.MessagingStyle.Message(
-                "text", 0, person.build()).toBundle() };
-        bundle.putParcelableArray(Notification.EXTRA_MESSAGES, messagesBundle);
-
-        Notification notification = new Notification.Builder(mContext, "test")
-                .addExtras(bundle)
-                .build();
-
-        NotificationEntry entry = new NotificationEntryBuilder()
-                .setPkg("pkg")
-                .setOpPkg("pkg")
-                .setTag("tag")
-                .setNotification(notification)
-                .setUser(mContext.getUser())
-                .setOverrideGroupKey("")
-                .build();
-        entry.setHasSentReply();
-
-        assertTrue(entry.isLastMessageFromReply());
-    }
-
-    @Test
-    public void personHighPriority() {
-        Person person = new Person.Builder()
-                .setName("name")
-                .setKey("abc")
-                .setUri("uri")
-                .setBot(true)
-                .build();
-
-        Notification notification = new Notification.Builder(mContext, "test")
-                .addPerson(person)
-                .build();
-
-        StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
-                notification, mContext.getUser(), "", 0);
-
-        assertTrue(mNotificationData.isHighPriority(sbn));
-    }
-
-    @Test
-    public void messagingStyleHighPriority() {
-
-        Notification notification = new Notification.Builder(mContext, "test")
-                .setStyle(new Notification.MessagingStyle(""))
-                .build();
-
-        StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
-                notification, mContext.getUser(), "", 0);
-
-        assertTrue(mNotificationData.isHighPriority(sbn));
-    }
-
-    @Test
-    public void minForegroundNotHighPriority() {
-        Notification notification = mock(Notification.class);
-        when(notification.isForegroundService()).thenReturn(true);
-
-        StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
-                notification, mContext.getUser(), "", 0);
-
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_MIN);
-        mNotificationData.rankingOverrides.put(sbn.getKey(), override);
-
-        assertFalse(mNotificationData.isHighPriority(sbn));
-    }
-
-    @Test
-    public void lowForegroundHighPriority() {
-        Notification notification = mock(Notification.class);
-        when(notification.isForegroundService()).thenReturn(true);
-
-        StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
-                notification, mContext.getUser(), "", 0);
-
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        mNotificationData.rankingOverrides.put(sbn.getKey(), override);
-
-        assertTrue(mNotificationData.isHighPriority(sbn));
-    }
-
-    @Test
-    public void userChangeTrumpsHighPriorityCharacteristics() {
-        Person person = new Person.Builder()
-                .setName("name")
-                .setKey("abc")
-                .setUri("uri")
-                .setBot(true)
-                .build();
-
-        Notification notification = new Notification.Builder(mContext, "test")
-                .addPerson(person)
-                .setStyle(new Notification.MessagingStyle(""))
-                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
-                .build();
-
-        StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
-                notification, mContext.getUser(), "", 0);
-
-        NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
-        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
-
-        Bundle override = new Bundle();
-        override.putParcelable(OVERRIDE_CHANNEL, channel);
-        mNotificationData.rankingOverrides.put(sbn.getKey(), override);
-
-        assertFalse(mNotificationData.isHighPriority(sbn));
-    }
-
-    @Test
-    public void testSort_highPriorityTrumpsNMSRank() {
-        // NMS rank says A and then B. But A is not high priority and B is, so B should sort in
-        // front
-        Notification aN = new Notification.Builder(mContext, "test")
-                .setStyle(new Notification.MessagingStyle(""))
-                .build();
-        NotificationEntry a = new NotificationEntryBuilder()
-                .setPkg("pkg")
-                .setOpPkg("pkg")
-                .setTag("tag")
-                .setNotification(aN)
-                .setUser(mContext.getUser())
-                .setOverrideGroupKey("")
-                .build();
-        a.setRow(mock(ExpandableNotificationRow.class));
-        a.setIsHighPriority(false);
-
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        override.putInt(OVERRIDE_RANK, 1);
-        mNotificationData.rankingOverrides.put(a.getKey(), override);
-
-        Notification bN = new Notification.Builder(mContext, "test")
-                .setStyle(new Notification.MessagingStyle(""))
-                .build();
-        NotificationEntry b = new NotificationEntryBuilder()
-                .setPkg("pkg2")
-                .setOpPkg("pkg2")
-                .setTag("tag")
-                .setNotification(bN)
-                .setUser(mContext.getUser())
-                .setOverrideGroupKey("")
-                .build();
-        b.setIsHighPriority(true);
-        b.setRow(mock(ExpandableNotificationRow.class));
-
-        Bundle bOverride = new Bundle();
-        bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        bOverride.putInt(OVERRIDE_RANK, 2);
-        mNotificationData.rankingOverrides.put(b.getKey(), bOverride);
-
-        assertEquals(1, mNotificationData.mRankingComparator.compare(a, b));
-    }
-
-    @Test
-    public void testSort_samePriorityUsesNMSRank() {
-        // NMS rank says A and then B, and they are the same priority so use that rank
-        Notification aN = new Notification.Builder(mContext, "test")
-                .setStyle(new Notification.MessagingStyle(""))
-                .build();
-        NotificationEntry a = new NotificationEntryBuilder()
-                .setPkg("pkg")
-                .setOpPkg("pkg")
-                .setTag("tag")
-                .setNotification(aN)
-                .setUser(mContext.getUser())
-                .setOverrideGroupKey("")
-                .build();
-        a.setRow(mock(ExpandableNotificationRow.class));
-        a.setIsHighPriority(false);
-
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        override.putInt(OVERRIDE_RANK, 1);
-        mNotificationData.rankingOverrides.put(a.getKey(), override);
-
-        Notification bN = new Notification.Builder(mContext, "test")
-                .setStyle(new Notification.MessagingStyle(""))
-                .build();
-        NotificationEntry b = new NotificationEntryBuilder()
-                .setPkg("pkg2")
-                .setOpPkg("pkg2")
-                .setTag("tag")
-                .setNotification(bN)
-                .setUser(mContext.getUser())
-                .setOverrideGroupKey("")
-                .build();
-        b.setRow(mock(ExpandableNotificationRow.class));
-        b.setIsHighPriority(false);
-
-        Bundle bOverride = new Bundle();
-        bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        bOverride.putInt(OVERRIDE_RANK, 2);
-        mNotificationData.rankingOverrides.put(b.getKey(), bOverride);
-
-        assertEquals(-1, mNotificationData.mRankingComparator.compare(a, b));
-    }
-
-    @Test
-    public void testSort_properlySetsAlertingBucket() {
-        Notification notification = new Notification.Builder(mContext, "test")
-                .build();
-        NotificationEntry entry = new NotificationEntryBuilder()
-                .setPkg("pkg")
-                .setOpPkg("pkg")
-                .setTag("tag")
-                .setNotification(notification)
-                .setUser(mContext.getUser())
-                .setOverrideGroupKey("")
-                .build();
-
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_DEFAULT);
-        mNotificationData.rankingOverrides.put(entry.getKey(), override);
-
-        entry.setRow(mRow);
-        mNotificationData.add(entry);
-
-        assertEquals(entry.getBucket(), BUCKET_ALERTING);
-    }
-
-    @Test
-    public void testSort_properlySetsSilentBucket() {
-        Notification notification = new Notification.Builder(mContext, "test")
-                .build();
-
-        NotificationEntry entry = new NotificationEntryBuilder()
-                .setPkg("pkg")
-                .setOpPkg("pkg")
-                .setTag("tag")
-                .setNotification(notification)
-                .setUser(mContext.getUser())
-                .setOverrideGroupKey("")
-                .build();
-
-        Bundle override = new Bundle();
-        override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        mNotificationData.rankingOverrides.put(entry.getKey(), override);
-
-        entry.setRow(mRow);
-        mNotificationData.add(entry);
-
-        assertEquals(entry.getBucket(), BUCKET_SILENT);
-    }
-
-    private void initStatusBarNotification(boolean allowDuringSetup) {
-        Bundle bundle = new Bundle();
-        bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
-        Notification notification = new Notification.Builder(mContext, "test")
-                .addExtras(bundle)
-                .build();
-        modifySbn(mEntry)
-                .setNotification(notification)
-                .build();
-    }
-
-    public static class TestableNotificationData extends NotificationData {
-        public TestableNotificationData(NotificationSectionsFeatureManager sectionsFeatureManager) {
-            super(
-                    sectionsFeatureManager,
-                    mock(NotifLog.class),
-                    mock(PeopleNotificationIdentifier.class));
-        }
-
-        public static final String OVERRIDE_RANK = "r";
-        public static final String OVERRIDE_DND = "dnd";
-        public static final String OVERRIDE_VIS_OVERRIDE = "vo";
-        public static final String OVERRIDE_VIS_EFFECTS = "ve";
-        public static final String OVERRIDE_IMPORTANCE = "i";
-        public static final String OVERRIDE_IMP_EXP = "ie";
-        public static final String OVERRIDE_GROUP = "g";
-        public static final String OVERRIDE_CHANNEL = "c";
-        public static final String OVERRIDE_PEOPLE = "p";
-        public static final String OVERRIDE_SNOOZE_CRITERIA = "sc";
-        public static final String OVERRIDE_BADGE = "b";
-        public static final String OVERRIDE_USER_SENTIMENT = "us";
-        public static final String OVERRIDE_HIDDEN = "h";
-        public static final String OVERRIDE_LAST_ALERTED = "la";
-        public static final String OVERRIDE_NOISY = "n";
-        public static final String OVERRIDE_SMART_ACTIONS = "sa";
-        public static final String OVERRIDE_SMART_REPLIES = "sr";
-        public static final String OVERRIDE_BUBBLE = "cb";
-        public static final String OVERRIDE_VISUALLY_INTERRUPTIVE = "vi";
-
-        public Map<String, Bundle> rankingOverrides = new HashMap<>();
-
-        @Override
-        protected boolean getRanking(String key, Ranking outRanking) {
-            super.getRanking(key, outRanking);
-
-            ArrayList<String> currentAdditionalPeople = new ArrayList<>();
-            if (outRanking.getAdditionalPeople() != null) {
-                currentAdditionalPeople.addAll(outRanking.getAdditionalPeople());
-            }
-
-            ArrayList<SnoozeCriterion> currentSnooze = new ArrayList<>();
-            if (outRanking.getSnoozeCriteria() != null) {
-                currentSnooze.addAll(outRanking.getSnoozeCriteria());
-            }
-
-            ArrayList<Notification.Action> currentActions = new ArrayList<>();
-            if (outRanking.getSmartActions() != null) {
-                currentActions.addAll(outRanking.getSmartActions());
-            }
-
-            ArrayList<CharSequence> currentReplies = new ArrayList<>();
-            if (outRanking.getSmartReplies() != null) {
-                currentReplies.addAll(outRanking.getSmartReplies());
-            }
-
-            if (rankingOverrides.get(key) != null) {
-                Bundle overrides = rankingOverrides.get(key);
-                outRanking.populate(key,
-                        overrides.getInt(OVERRIDE_RANK, outRanking.getRank()),
-                        overrides.getBoolean(OVERRIDE_DND, outRanking.matchesInterruptionFilter()),
-                        overrides.getInt(OVERRIDE_VIS_OVERRIDE, outRanking.getVisibilityOverride()),
-                        overrides.getInt(OVERRIDE_VIS_EFFECTS,
-                                outRanking.getSuppressedVisualEffects()),
-                        overrides.getInt(OVERRIDE_IMPORTANCE, outRanking.getImportance()),
-                        overrides.getCharSequence(OVERRIDE_IMP_EXP,
-                                outRanking.getImportanceExplanation()),
-                        overrides.getString(OVERRIDE_GROUP, outRanking.getOverrideGroupKey()),
-                        overrides.containsKey(OVERRIDE_CHANNEL)
-                                ? (NotificationChannel) overrides.getParcelable(OVERRIDE_CHANNEL)
-                                : outRanking.getChannel(),
-                        overrides.containsKey(OVERRIDE_PEOPLE)
-                                ? overrides.getStringArrayList(OVERRIDE_PEOPLE)
-                                : currentAdditionalPeople,
-                        overrides.containsKey(OVERRIDE_SNOOZE_CRITERIA)
-                                ? overrides.getParcelableArrayList(OVERRIDE_SNOOZE_CRITERIA)
-                                : currentSnooze,
-                        overrides.getBoolean(OVERRIDE_BADGE, outRanking.canShowBadge()),
-                        overrides.getInt(OVERRIDE_USER_SENTIMENT, outRanking.getUserSentiment()),
-                        overrides.getBoolean(OVERRIDE_HIDDEN, outRanking.isSuspended()),
-                        overrides.getLong(OVERRIDE_LAST_ALERTED,
-                                outRanking.getLastAudiblyAlertedMillis()),
-                        overrides.getBoolean(OVERRIDE_NOISY, outRanking.isNoisy()),
-                        overrides.containsKey(OVERRIDE_SMART_ACTIONS)
-                                ? overrides.getParcelableArrayList(OVERRIDE_SMART_ACTIONS)
-                                : currentActions,
-                        overrides.containsKey(OVERRIDE_SMART_REPLIES)
-                                ? overrides.getCharSequenceArrayList(OVERRIDE_SMART_REPLIES)
-                                : currentReplies,
-                        overrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()),
-                        overrides.getBoolean(OVERRIDE_VISUALLY_INTERRUPTIVE,
-                                outRanking.visuallyInterruptive()));
-            } else {
-                outRanking.populate(
-                        new RankingBuilder()
-                                .setKey(key)
-                                .build());
-            }
-            return true;
-        }
-    }
-
-    private Notification.Action createContextualAction(String title) {
-        return new Notification.Action.Builder(
-                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
-                title,
-                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0))
-                        .setContextual(true)
-                        .build();
-    }
-
-    private Notification.Action createAction(String title) {
-        return new Notification.Action.Builder(
-                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
-                title,
-                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
-    }
-
-    private ArrayList<Notification.Action> createActions(String... titles) {
-        ArrayList<Notification.Action> actions = new ArrayList<>();
-        for (String title : titles) {
-            actions.add(createAction(title));
-        }
-        return actions;
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
new file mode 100644
index 0000000..536aeb4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -0,0 +1,254 @@
+/*
+ * 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.notification.collection;
+
+import static android.app.Notification.CATEGORY_ALARM;
+import static android.app.Notification.CATEGORY_CALL;
+import static android.app.Notification.CATEGORY_EVENT;
+import static android.app.Notification.CATEGORY_MESSAGE;
+import static android.app.Notification.CATEGORY_REMINDER;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+
+import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
+import static com.android.systemui.statusbar.NotificationEntryHelper.modifySbn;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.PendingIntent;
+import android.app.Person;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.media.session.MediaSession;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.SnoozeCriterion;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.SbnBuilder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class NotificationEntryTest extends SysuiTestCase {
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+    private static final int UID_NORMAL = 123;
+    private static final NotificationChannel NOTIFICATION_CHANNEL =
+            new NotificationChannel("id", "name", NotificationChannel.USER_LOCKED_IMPORTANCE);
+
+    private int mId;
+
+    private NotificationEntry mEntry;
+
+    @Before
+    public void setup() {
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+
+        mEntry = new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_NAME)
+                .setOpPkg(TEST_PACKAGE_NAME)
+                .setUid(TEST_UID)
+                .setId(mId++)
+                .setNotification(n.build())
+                .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+                .build();
+    }
+
+    @Test
+    public void testIsExemptFromDndVisualSuppression_foreground() {
+        mEntry.getSbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+
+        assertTrue(mEntry.isExemptFromDndVisualSuppression());
+        assertFalse(mEntry.shouldSuppressAmbient());
+    }
+
+    @Test
+    public void testIsExemptFromDndVisualSuppression_media() {
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setStyle(new Notification.MediaStyle()
+                        .setMediaSession(mock(MediaSession.Token.class)))
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+        NotificationEntry e1 = new NotificationEntryBuilder()
+                .setNotification(n.build())
+                .build();
+
+        assertTrue(e1.isExemptFromDndVisualSuppression());
+        assertFalse(e1.shouldSuppressAmbient());
+    }
+
+    @Test
+    public void testIsExemptFromDndVisualSuppression_system() {
+        mEntry.mIsSystemNotification = true;
+
+        assertTrue(mEntry.isExemptFromDndVisualSuppression());
+        assertFalse(mEntry.shouldSuppressAmbient());
+    }
+
+    @Test
+    public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
+        NotificationEntry entry = new NotificationEntryBuilder()
+                .setUid(UID_NORMAL)
+                .build();
+        entry.mIsSystemNotification = true;
+        modifyRanking(entry).setSuppressedVisualEffects(SUPPRESSED_EFFECT_AMBIENT).build();
+
+        modifySbn(entry)
+                .setNotification(
+                        new Notification.Builder(mContext, "").setCategory(CATEGORY_CALL).build())
+                .build();
+        assertFalse(entry.isExemptFromDndVisualSuppression());
+        assertTrue(entry.shouldSuppressAmbient());
+
+        modifySbn(entry)
+                .setNotification(
+                        new Notification.Builder(mContext, "")
+                                .setCategory(CATEGORY_REMINDER)
+                                .build())
+                .build();
+        assertFalse(entry.isExemptFromDndVisualSuppression());
+
+        modifySbn(entry)
+                .setNotification(
+                        new Notification.Builder(mContext, "").setCategory(CATEGORY_ALARM).build())
+                .build();
+        assertFalse(entry.isExemptFromDndVisualSuppression());
+
+        modifySbn(entry)
+                .setNotification(
+                        new Notification.Builder(mContext, "").setCategory(CATEGORY_EVENT).build())
+                .build();
+        assertFalse(entry.isExemptFromDndVisualSuppression());
+
+        modifySbn(entry)
+                .setNotification(
+                        new Notification.Builder(mContext, "")
+                                .setCategory(CATEGORY_MESSAGE)
+                                .build())
+                .build();
+        assertFalse(entry.isExemptFromDndVisualSuppression());
+    }
+
+    @Test
+    public void testCreateNotificationDataEntry_RankingUpdate() {
+        StatusBarNotification sbn = new SbnBuilder().build();
+        sbn.getNotification().actions =
+                new Notification.Action[]{createContextualAction("appGeneratedAction")};
+
+        ArrayList<Notification.Action> systemGeneratedSmartActions =
+                createActions("systemGeneratedAction");
+
+        SnoozeCriterion snoozeCriterion = new SnoozeCriterion("id", "explanation", "confirmation");
+        ArrayList<SnoozeCriterion> snoozeCriterions = new ArrayList<>();
+        snoozeCriterions.add(snoozeCriterion);
+
+        Ranking ranking = new RankingBuilder()
+                .setKey(sbn.getKey())
+                .setSmartActions(systemGeneratedSmartActions)
+                .setChannel(NOTIFICATION_CHANNEL)
+                .setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
+                .setSnoozeCriteria(snoozeCriterions)
+                .build();
+
+        NotificationEntry entry =
+                new NotificationEntry(sbn, ranking);
+
+        assertEquals(systemGeneratedSmartActions, entry.getSmartActions());
+        assertEquals(NOTIFICATION_CHANNEL, entry.getChannel());
+        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.getUserSentiment());
+        assertEquals(snoozeCriterions, entry.getSnoozeCriteria());
+    }
+
+    @Test
+    public void notificationDataEntry_testIsLastMessageFromReply() {
+        Person.Builder person = new Person.Builder()
+                .setName("name")
+                .setKey("abc")
+                .setUri("uri")
+                .setBot(true);
+
+        // EXTRA_MESSAGING_PERSON is the same Person as the sender in last message in EXTRA_MESSAGES
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(Notification.EXTRA_MESSAGING_PERSON, person.build());
+        Bundle[] messagesBundle = new Bundle[]{new Notification.MessagingStyle.Message(
+                "text", 0, person.build()).toBundle()};
+        bundle.putParcelableArray(Notification.EXTRA_MESSAGES, messagesBundle);
+
+        Notification notification = new Notification.Builder(mContext, "test")
+                .addExtras(bundle)
+                .build();
+
+        NotificationEntry entry = new NotificationEntryBuilder()
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(notification)
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build();
+        entry.setHasSentReply();
+
+        assertTrue(entry.isLastMessageFromReply());
+    }
+
+    private Notification.Action createContextualAction(String title) {
+        return new Notification.Action.Builder(
+                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
+                title,
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0))
+                .setContextual(true)
+                .build();
+    }
+
+    private Notification.Action createAction(String title) {
+        return new Notification.Action.Builder(
+                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
+                title,
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
+    }
+
+    private ArrayList<Notification.Action> createActions(String... titles) {
+        ArrayList<Notification.Action> actions = new ArrayList<>();
+        for (String title : titles) {
+            actions.add(createAction(title));
+        }
+        return actions;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
new file mode 100644
index 0000000..01b2f89
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -0,0 +1,318 @@
+/*
+ * 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.notification.collection
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager.IMPORTANCE_DEFAULT
+import android.app.NotificationManager.IMPORTANCE_LOW
+import android.app.Person
+import android.service.notification.NotificationListenerService.RankingMap
+import android.service.notification.StatusBarNotification
+import android.testing.AndroidTestingRunner
+
+import org.junit.runner.RunWith
+
+import androidx.test.filters.SmallTest
+
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.NotificationEntryBuilder
+import com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking
+import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.notification.NotificationFilter
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
+import com.android.systemui.statusbar.notification.logging.NotifLog
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
+import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import dagger.Lazy
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class NotificationRankingManagerTest
+    : SysuiTestCase() {
+
+    private var lazyMedia: Lazy<NotificationMediaManager> = Lazy {
+        mock<NotificationMediaManager>(NotificationMediaManager::class.java)
+    }
+
+    private val rankingManager = TestableNotificationRankingManager(
+            lazyMedia,
+            mock<NotificationGroupManager>(NotificationGroupManager::class.java),
+            mock<HeadsUpManager>(HeadsUpManager::class.java),
+            mock<NotificationFilter>(NotificationFilter::class.java),
+            mock<NotifLog>(NotifLog::class.java),
+            mock<NotificationSectionsFeatureManager>(NotificationSectionsFeatureManager::class.java)
+    )
+
+    @Before
+    fun setup() {
+    }
+
+    @Test
+    fun testPeopleNotification_isHighPriority() {
+        val person = Person.Builder()
+                .setName("name")
+                .setKey("abc")
+                .setUri("uri")
+                .setBot(true)
+                .build()
+
+        val notification = Notification.Builder(mContext, "test")
+                .addPerson(person)
+                .build()
+
+        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+                notification, mContext.user, "", 0)
+
+        val e = NotificationEntryBuilder()
+                .setNotification(notification)
+                .setSbn(sbn)
+                .build()
+
+        assertTrue(rankingManager.isHighPriority2(e))
+    }
+
+    @Test
+    fun messagingStyleHighPriority() {
+
+        val notif = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+
+        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+                notif, mContext.getUser(), "", 0)
+
+        val e = NotificationEntryBuilder()
+                .setNotification(notif)
+                .setSbn(sbn)
+                .build()
+
+        assertTrue(rankingManager.isHighPriority2(e))
+    }
+
+    @Test
+    fun lowForegroundHighPriority() {
+        val notification = mock(Notification::class.java)
+        `when`<Boolean>(notification.isForegroundService).thenReturn(true)
+
+        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+                notification, mContext.user, "", 0)
+
+        val e = NotificationEntryBuilder()
+                .setNotification(notification)
+                .setSbn(sbn)
+                .build()
+
+        modifyRanking(e)
+                .setImportance(IMPORTANCE_LOW)
+                .build()
+
+        assertTrue(rankingManager.isHighPriority2(e))
+    }
+
+    @Test
+    fun userChangeTrumpsHighPriorityCharacteristics() {
+        val person = Person.Builder()
+                .setName("name")
+                .setKey("abc")
+                .setUri("uri")
+                .setBot(true)
+                .build()
+
+        val notification = Notification.Builder(mContext, "test")
+                .addPerson(person)
+                .setStyle(Notification.MessagingStyle(""))
+                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+                .build()
+
+        val sbn = StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+                notification, mContext.user, "", 0)
+
+        val channel = NotificationChannel("a", "a", IMPORTANCE_LOW)
+        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE)
+
+        val e = NotificationEntryBuilder()
+                .setSbn(sbn)
+                .setChannel(channel)
+                .build()
+
+        assertFalse(rankingManager.isHighPriority2(e))
+    }
+
+    @Test
+    fun testSort_highPriorityTrumpsNMSRank() {
+        // NMS rank says A and then B. But A is not high priority and B is, so B should sort in
+        // front
+        val aN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val a = NotificationEntryBuilder()
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(aN)
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+
+        a.setIsHighPriority(false)
+
+        modifyRanking(a)
+                .setImportance(IMPORTANCE_LOW)
+                .setRank(1)
+                .build()
+
+        val bN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val b = NotificationEntryBuilder()
+                .setPkg("pkg2")
+                .setOpPkg("pkg2")
+                .setTag("tag")
+                .setNotification(bN)
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+        b.setIsHighPriority(true)
+
+        modifyRanking(b)
+                .setImportance(IMPORTANCE_LOW)
+                .setRank(2)
+                .build()
+
+        assertEquals(
+                listOf(b, a),
+                rankingManager.updateRanking(null, listOf(a, b), "test"))
+    }
+
+    @Test
+    fun testSort_samePriorityUsesNMSRank() {
+        // NMS rank says A and then B, and they are the same priority so use that rank
+        val aN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val a = NotificationEntryBuilder()
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(aN)
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+        a.setIsHighPriority(false)
+
+        modifyRanking(a)
+                .setImportance(IMPORTANCE_LOW)
+                .setRank(1)
+                .build()
+
+        val bN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val b = NotificationEntryBuilder()
+                .setPkg("pkg2")
+                .setOpPkg("pkg2")
+                .setTag("tag")
+                .setNotification(bN)
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+        b.setIsHighPriority(false)
+
+        modifyRanking(b)
+                .setImportance(IMPORTANCE_LOW)
+                .setRank(2)
+                .build()
+
+        assertEquals(
+                listOf(a, b),
+                rankingManager.updateRanking(null, listOf(a, b), "test"))
+    }
+
+    @Test
+    fun testSort_properlySetsAlertingBucket() {
+        val notif = Notification.Builder(mContext, "test") .build()
+
+        val e = NotificationEntryBuilder()
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(notif)
+                .setUser(mContext.user)
+                .setOverrideGroupKey("")
+                .build()
+
+        modifyRanking(e).setImportance(IMPORTANCE_DEFAULT) .build()
+
+        rankingManager.updateRanking(RankingMap(arrayOf(e.ranking)), listOf(e), "test")
+        assertEquals(e.bucket, BUCKET_ALERTING)
+    }
+
+    @Test
+    fun testSort_properlySetsSilentBucket() {
+        val notif = Notification.Builder(mContext, "test") .build()
+
+        val e = NotificationEntryBuilder()
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(notif)
+                .setUser(mContext.user)
+                .setOverrideGroupKey("")
+                .build()
+
+        modifyRanking(e).setImportance(IMPORTANCE_LOW).build()
+
+        rankingManager.updateRanking(RankingMap(arrayOf(e.ranking)), listOf(e), "test")
+        assertEquals(e.bucket, BUCKET_SILENT)
+    }
+
+    internal class TestableNotificationRankingManager(
+        mediaManager: Lazy<NotificationMediaManager>,
+        groupManager: NotificationGroupManager,
+        headsUpManager: HeadsUpManager,
+        filter: NotificationFilter,
+        notifLog: NotifLog,
+        sectionsFeatureManager: NotificationSectionsFeatureManager
+    ) : NotificationRankingManager(
+        mediaManager,
+        groupManager,
+        headsUpManager,
+        filter,
+        notifLog,
+        sectionsFeatureManager
+    ) {
+
+        fun isHighPriority2(e: NotificationEntry): Boolean {
+            return isHighPriority(e)
+        }
+
+        fun applyTestRankingMap(r: RankingMap) {
+            rankingMap = r
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 47c17ad..d139866 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -44,7 +44,6 @@
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -71,7 +70,6 @@
 
     @Mock private NotificationListContainer mListContainer;
     @Mock private IStatusBarService mBarService;
-    @Mock private NotificationData mNotificationData;
     @Mock private ExpandableNotificationRow mRow;
     @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
 
@@ -91,8 +89,6 @@
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
         mDependency.injectTestDependency(NotificationListener.class, mListener);
 
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
-
         mEntry = new NotificationEntryBuilder()
                 .setPkg(TEST_PACKAGE_NAME)
                 .setOpPkg(TEST_PACKAGE_NAME)
@@ -131,7 +127,7 @@
                 any(NotificationVisibility[].class));
 
         when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
-        when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
+        when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
         mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
         TestableLooper.get(this).processAllMessages();
         waitForUiOffloadThread();
@@ -153,7 +149,7 @@
     public void testStoppingNotificationLoggingReportsCurrentNotifications()
             throws Exception {
         when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
-        when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
+        when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
         mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
         TestableLooper.get(this).processAllMessages();
         waitForUiOffloadThread();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 6f52e4a..5b624bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -20,7 +20,6 @@
 import static junit.framework.Assert.assertNull;
 
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -56,7 +55,9 @@
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.NotificationEntryBuilder;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShelf;
@@ -65,9 +66,13 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationFilter;
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.TestableNotificationEntryManager;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.FooterView;
@@ -80,7 +85,6 @@
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEntryManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.util.DeviceConfigProxyFake;
@@ -97,6 +101,7 @@
 import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Tests for {@link NotificationStackScrollLayout}.
@@ -117,7 +122,6 @@
     @Mock private NotificationGroupManager mGroupManager;
     @Mock private ExpandHelper mExpandHelper;
     @Mock private EmptyShadeView mEmptyShadeView;
-    @Mock private NotificationData mNotificationData;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
     @Mock private RemoteInputController mRemoteInputController;
     @Mock private NotificationIconAreaController mNotificationIconAreaController;
@@ -140,6 +144,7 @@
                 NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
 
         // Inject dependencies before initializing the layout
+        mDependency.injectMockDependency(VisualStabilityManager.class);
         mDependency.injectTestDependency(
                 NotificationBlockingHelperManager.class,
                 mBlockingHelperManager);
@@ -150,7 +155,18 @@
         mDependency.injectMockDependency(ShadeController.class);
         when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
 
-        mEntryManager = new TestableNotificationEntryManager(mNotificationData);
+        mEntryManager = new TestableNotificationEntryManager(
+                mock(NotifLog.class),
+                mock(NotificationGroupManager.class),
+                new NotificationRankingManager(
+                        () -> mock(NotificationMediaManager.class),
+                        mGroupManager,
+                        mHeadsUpManager,
+                        mock(NotificationFilter.class),
+                        mock(NotifLog.class),
+                        mock(NotificationSectionsFeatureManager.class)
+                ),
+                mock(NotificationEntryManager.KeyguardEnvironment.class));
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
         Dependency.get(InitController.class).executePostInitTasks();
         mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, mHeadsUpManager);
@@ -161,8 +177,8 @@
         // The actual class under test.  You may need to work with this class directly when
         // testing anonymous class members of mStackScroller, like mMenuEventListener,
         // which refer to members of NotificationStackScrollLayout. The spy
-        // holds a copy of the CUT's instances of these classes, so they still refer to the CUT's
-        // member variables, not the spy's member variables.
+        // holds a copy of the CUT's instances of these KeyguardBypassController, so they still
+        // refer to the CUT's member variables, not the spy's member variables.
         mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null,
                 true /* allowLongPress */, mNotificationRoundnessManager,
                 mock(DynamicPrivacyController.class),
@@ -293,7 +309,7 @@
     @Test
     public void testUpdateFooter_noNotifications() {
         setBarStateForTest(StatusBarState.SHADE);
-        assertEquals(0, mNotificationData.getActiveNotifications().size());
+        assertEquals(0, mEntryManager.getActiveNotificationsCount());
 
         mStackScroller.updateFooter();
         verify(mStackScroller, atLeastOnce()).updateFooterView(false, false);
@@ -303,8 +319,8 @@
     public void testUpdateFooter_remoteInput() {
         setBarStateForTest(StatusBarState.SHADE);
         ArrayList<NotificationEntry> entries = new ArrayList<>();
-        entries.add(mock(NotificationEntry.class));
-        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
+        entries.add(new NotificationEntryBuilder().build());
+        addEntriesToEntryManager(entries);
 
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
         when(row.canViewBeDismissed()).thenReturn(true);
@@ -319,9 +335,10 @@
     @Test
     public void testUpdateFooter_oneClearableNotification() {
         setBarStateForTest(StatusBarState.SHADE);
+
         ArrayList<NotificationEntry> entries = new ArrayList<>();
-        entries.add(mock(NotificationEntry.class));
-        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
+        entries.add(new NotificationEntryBuilder().build());
+        addEntriesToEntryManager(entries);
 
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
         when(row.canViewBeDismissed()).thenReturn(true);
@@ -335,10 +352,10 @@
     @Test
     public void testUpdateFooter_oneNonClearableNotification() {
         setBarStateForTest(StatusBarState.SHADE);
+
         ArrayList<NotificationEntry> entries = new ArrayList<>();
-        entries.add(mock(NotificationEntry.class));
-        when(mEntryManager.getNotificationData().getActiveNotifications()).thenReturn(entries);
-        assertTrue(mEntryManager.getNotificationData().getActiveNotifications().size() != 0);
+        entries.add(new NotificationEntryBuilder().build());
+        addEntriesToEntryManager(entries);
 
         mStackScroller.updateFooter();
         verify(mStackScroller).updateFooterView(true, false);
@@ -460,4 +477,14 @@
         // rather than the mock because the spy just coppied the anonymous inner /shruggie.
         mStackScroller.setStatusBarState(state);
     }
+
+    private void addEntriesToEntryManager(List<NotificationEntry> entries) {
+        for (NotificationEntry e : entries) {
+            mEntryManager.addActiveNotificationForTest(e);
+        }
+    }
+
+    private void addActiveNotificationsToManager(List<NotificationEntry> entries) {
+        mEntryManager.setActiveNotificationList(entries);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
index 64c1b51..a024454 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
@@ -40,7 +40,6 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 import org.junit.Before;
@@ -51,8 +50,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
@@ -61,7 +58,6 @@
     private static final int LIGHTS_OUT = APPEARANCE_LOW_PROFILE_BARS;
 
     @Mock private NotificationEntryManager mEntryManager;
-    @Mock private NotificationData mNotificationData;
     @Mock private CommandQueue mCommandQueue;
     @Mock private WindowManager mWindowManager;
     @Mock private Display mDisplay;
@@ -71,7 +67,6 @@
 
     private View mLightsOutView;
     private LightsOutNotifController mLightsOutNotifController;
-    private ArrayList<NotificationEntry> mActiveNotifications = new ArrayList<>();
     private int mDisplayId;
     private NotificationEntryListener mEntryListener;
     private CommandQueue.Callbacks mCallbacks;
@@ -81,8 +76,6 @@
         MockitoAnnotations.initMocks(this);
         mDisplayId = mContext.getDisplayId();
         mLightsOutView = new View(mContext);
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
-        when(mNotificationData.getActiveNotifications()).thenReturn(mActiveNotifications);
         when(mWindowManager.getDefaultDisplay()).thenReturn(mDisplay);
         when(mDisplay.getDisplayId()).thenReturn(mDisplayId);
 
@@ -136,7 +129,7 @@
     @Test
     public void testLightsOut_withNotifs_onSystemBarAppearanceChanged() {
         // GIVEN active visible notifications
-        mActiveNotifications.add(mock(NotificationEntry.class));
+        when(mEntryManager.hasActiveNotifications()).thenReturn(true);
 
         // WHEN lights out
         mCallbacks.onSystemBarAppearanceChanged(
@@ -153,7 +146,7 @@
     @Test
     public void testLightsOut_withoutNotifs_onSystemBarAppearanceChanged() {
         // GIVEN no active visible notifications
-        mActiveNotifications.clear();
+        when(mEntryManager.hasActiveNotifications()).thenReturn(false);
 
         // WHEN lights out
         mCallbacks.onSystemBarAppearanceChanged(
@@ -170,7 +163,7 @@
     @Test
     public void testLightsOn_afterLightsOut_onSystemBarAppearanceChanged() {
         // GIVEN active visible notifications
-        mActiveNotifications.add(mock(NotificationEntry.class));
+        when(mEntryManager.hasActiveNotifications()).thenReturn(true);
 
         // WHEN lights on
         mCallbacks.onSystemBarAppearanceChanged(
@@ -187,13 +180,13 @@
     @Test
     public void testEntryAdded() {
         // GIVEN no visible notifications and lights out
-        mActiveNotifications.clear();
+        when(mEntryManager.hasActiveNotifications()).thenReturn(false);
         mLightsOutNotifController.mAppearance = LIGHTS_OUT;
         mLightsOutNotifController.updateLightsOutView();
         assertIsShowingDot(false);
 
         // WHEN an active notification is added
-        mActiveNotifications.add(mock(NotificationEntry.class));
+        when(mEntryManager.hasActiveNotifications()).thenReturn(true);
         assertTrue(mLightsOutNotifController.shouldShowDot());
         mEntryListener.onNotificationAdded(mock(NotificationEntry.class));
 
@@ -204,13 +197,13 @@
     @Test
     public void testEntryRemoved() {
         // GIVEN a visible notification and lights out
-        mActiveNotifications.add(mock(NotificationEntry.class));
+        when(mEntryManager.hasActiveNotifications()).thenReturn(true);
         mLightsOutNotifController.mAppearance = LIGHTS_OUT;
         mLightsOutNotifController.updateLightsOutView();
         assertIsShowingDot(true);
 
         // WHEN all active notifications are removed
-        mActiveNotifications.clear();
+        when(mEntryManager.hasActiveNotifications()).thenReturn(false);
         assertFalse(mLightsOutNotifController.shouldShowDot());
         mEntryListener.onEntryRemoved(mock(NotificationEntry.class), null, false);
 
@@ -221,13 +214,13 @@
     @Test
     public void testEntryUpdated() {
         // GIVEN no visible notifications and lights out
-        mActiveNotifications.clear();
+        when(mEntryManager.hasActiveNotifications()).thenReturn(false);
         mLightsOutNotifController.mAppearance = LIGHTS_OUT;
         mLightsOutNotifController.updateLightsOutView();
         assertIsShowingDot(false);
 
         // WHEN an active notification is added
-        mActiveNotifications.add(mock(NotificationEntry.class));
+        when(mEntryManager.hasActiveNotifications()).thenReturn(true);
         assertTrue(mLightsOutNotifController.shouldShowDot());
         mEntryListener.onPostEntryUpdated(mock(NotificationEntry.class));
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 280cc90..c165e56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -54,11 +54,9 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -239,11 +237,10 @@
                     mock(ShadeController.class),
                     mock(NotificationLockscreenUserManager.class),
                     new NotificationEntryManager(
-                            new NotificationData(
-                                    mock(NotificationSectionsFeatureManager.class),
-                                    mock(NotifLog.class),
-                                    mock(PeopleNotificationIdentifier.class)),
-                            mock(NotifLog.class)),
+                            mock(NotifLog.class),
+                            mock(NotificationGroupManager.class),
+                            mock(NotificationRankingManager.class),
+                            mock(NotificationEntryManager.KeyguardEnvironment.class)),
                     mock(KeyguardStateController.class),
                     statusBarStateController,
                     mock(DozeLog.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index d8a68b0..24a5d93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -68,7 +68,6 @@
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -117,7 +116,6 @@
     @Mock
     private Intent mContentIntentInner;
     @Mock
-    private NotificationData mNotificationData;
 
     private NotificationActivityStarter mNotificationActivityStarter;
 
@@ -134,7 +132,6 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
-        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
 
         when(mContentIntent.isActivity()).thenReturn(true);
         when(mContentIntent.getCreatorUserHandle()).thenReturn(UserHandle.of(1));
@@ -157,7 +154,7 @@
         mActiveNotifications = new ArrayList<>();
         mActiveNotifications.add(mNotificationRow.getEntry());
         mActiveNotifications.add(mBubbleNotificationRow.getEntry());
-        when(mNotificationData.getActiveNotifications()).thenReturn(mActiveNotifications);
+        when(mEntryManager.getVisibleNotifications()).thenReturn(mActiveNotifications);
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
 
         mNotificationActivityStarter = new StatusBarNotificationActivityStarter(getContext(),
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 de87d31..1c02b60 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
@@ -52,7 +52,6 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -100,11 +99,9 @@
         mDependency.injectMockDependency(NotificationGutsManager.class);
         mDependency.injectMockDependency(StatusBarWindowController.class);
         mDependency.injectMockDependency(InitController.class);
-        NotificationData notificationData = mock(NotificationData.class);
-        when(notificationData.getNotificationsForCurrentUser()).thenReturn(new ArrayList<>());
         NotificationEntryManager entryManager =
                 mDependency.injectMockDependency(NotificationEntryManager.class);
-        when(entryManager.getNotificationData()).thenReturn(notificationData);
+        when(entryManager.getActiveNotificationsForCurrentUser()).thenReturn(new ArrayList<>());
 
         StatusBarWindowView statusBarWindowView = mock(StatusBarWindowView.class);
         when(statusBarWindowView.getResources()).thenReturn(mContext.getResources());
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 f327378..95929c3a 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
@@ -101,7 +101,6 @@
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.PulseExpansionHandler;
@@ -120,12 +119,9 @@
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -177,7 +173,6 @@
     @Mock private ArrayList<NotificationEntry> mNotificationList;
     @Mock private Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
     @Mock private BiometricUnlockController mBiometricUnlockController;
-    @Mock private NotificationData mNotificationData;
     @Mock private NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
     @Mock private VisualStabilityManager mVisualStabilityManager;
     @Mock private NotificationListener mNotificationListener;
@@ -240,6 +235,7 @@
     @Mock private ViewMediatorCallback mViewMediatorCallback;
     @Mock private DismissCallbackRegistry mDismissCallbackRegistry;
     @Mock private ScreenPinningRequest mScreenPinningRequest;
+    @Mock private NotificationEntryManager mEntryManager;
 
     @Before
     public void setup() throws Exception {
@@ -260,10 +256,8 @@
         mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
 
         mMetricsLogger = new FakeMetricsLogger();
-        TestableNotificationEntryManager entryManager = new TestableNotificationEntryManager(
-                mNotificationData);
         NotificationLogger notificationLogger = new NotificationLogger(mNotificationListener,
-                Dependency.get(UiOffloadThread.class), entryManager, mStatusBarStateController,
+                Dependency.get(UiOffloadThread.class), mEntryManager, mStatusBarStateController,
                 mExpansionStateLogger);
         notificationLogger.setVisibilityReporter(mock(Runnable.class));
 
@@ -332,7 +326,7 @@
                 ),
                 mNotificationGutsManager,
                 notificationLogger,
-                entryManager,
+                mEntryManager,
                 mNotificationInterruptionStateProvider,
                 mNotificationViewHierarchyManager,
                 mKeyguardViewMediator,
@@ -407,9 +401,6 @@
         mStatusBar.mStatusBarWindowViewController = mStatusBarWindowViewController;
         mStatusBar.startKeyguard();
         Dependency.get(InitController.class).executePostInitTasks();
-        entryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller,
-                mHeadsUpManager);
-        entryManager.addNotificationEntryListener(mEntryListener);
         notificationLogger.setUpWithContainer(mStackScroller);
     }
 
@@ -645,8 +636,7 @@
     public void testPanelOpenForHeadsUp() {
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
         when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
-        when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
-        when(mNotificationList.size()).thenReturn(5);
+        when(mEntryManager.getActiveNotificationsCount()).thenReturn(5);
         when(mNotificationPresenter.isPresenterFullyCollapsed()).thenReturn(true);
         mStatusBar.setBarStateForTest(StatusBarState.SHADE);
 
@@ -664,8 +654,8 @@
     @Test
     public void testPanelOpenAndClear() {
         when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
-        when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
-        when(mNotificationList.size()).thenReturn(5);
+        when(mEntryManager.getActiveNotificationsCount()).thenReturn(5);
+
         when(mNotificationPresenter.isPresenterFullyCollapsed()).thenReturn(false);
         mStatusBar.setBarStateForTest(StatusBarState.SHADE);
 
@@ -683,8 +673,7 @@
     @Test
     public void testPanelOpenAndNoClear() {
         when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
-        when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
-        when(mNotificationList.size()).thenReturn(5);
+        when(mEntryManager.getActiveNotificationsCount()).thenReturn(5);
         when(mNotificationPresenter.isPresenterFullyCollapsed()).thenReturn(false);
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
 
@@ -842,19 +831,6 @@
                 any(UserHandle.class));
     }
 
-    public static class TestableNotificationEntryManager extends NotificationEntryManager {
-
-        public TestableNotificationEntryManager(NotificationData notificationData) {
-            super(notificationData, mock(NotifLog.class));
-        }
-
-        public void setUpForTest(NotificationPresenter presenter,
-                NotificationListContainer listContainer,
-                HeadsUpManagerPhone headsUpManager) {
-            super.setUpWithPresenter(presenter, listContainer, headsUpManager);
-        }
-    }
-
     public static class TestableNotificationInterruptionStateProvider extends
             NotificationInterruptionStateProvider {