Update NotificationIconAreaController

- Make NIAC injectable
- Pass the list of visible notifications to the NIAC instead of relying
on the views being shown in NSSL since the new pipeline uses the
notifications from the data-layer
- In the new pipeline, make the new NotifViewManager trigger the update
of the status bar notification icons

Test: atest SystemUITests
Test: manual (turn on new notification pipeline rendering, see notif icons are
visible in the status bar and in the notification shade)

Change-Id: I885b822da7135d9bd1de2ba123ab6686491d8f6c
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 7023e47..f5c3649 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -27,24 +27,15 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.dagger.DaggerGlobalRootComponent;
 import com.android.systemui.dagger.GlobalRootComponent;
 import com.android.systemui.dagger.SysUIComponent;
 import com.android.systemui.dagger.WMComponent;
-import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import java.util.concurrent.Executor;
@@ -151,19 +142,4 @@
                 Dependency.get(KeyguardUpdateMonitor.class), bypassController,
                 new Handler(Looper.getMainLooper()));
     }
-
-    public NotificationIconAreaController createNotificationIconAreaController(Context context,
-            StatusBar statusBar,
-            NotificationWakeUpCoordinator wakeUpCoordinator,
-            KeyguardBypassController keyguardBypassController,
-            StatusBarStateController statusBarStateController,
-            DemoModeController demoModeController) {
-        return new NotificationIconAreaController(context, statusBar, statusBarStateController,
-                wakeUpCoordinator, keyguardBypassController,
-                Dependency.get(NotificationMediaManager.class),
-                Dependency.get(NotificationListener.class),
-                Dependency.get(DozeParameters.class),
-                Dependency.get(BubbleController.class),
-                demoModeController);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 54e5453..1326d92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -27,7 +27,6 @@
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.statusbar.phone.PanelExpansionListener
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
@@ -98,7 +97,6 @@
         }
 
     private var collapsedEnoughToHide: Boolean = false
-    lateinit var iconAreaController: NotificationIconAreaController
 
     var pulsing: Boolean = false
         set(value) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 201be59..118ff4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
+import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import java.lang.RuntimeException
 import javax.inject.Inject
 
@@ -31,7 +32,8 @@
 class ShadeViewManager constructor(
     listContainer: NotificationListContainer,
     logger: ShadeViewDifferLogger,
-    private val viewBarn: NotifViewBarn
+    private val viewBarn: NotifViewBarn,
+    private val notificationIconAreaController: NotificationIconAreaController
 ) {
     private val rootController = RootNodeController(listContainer)
     private val viewDiffer = ShadeViewDiffer(rootController, logger)
@@ -52,6 +54,7 @@
             root.children.add(buildNotifNode(entry, root))
         }
 
+        notificationIconAreaController.updateNotificationIcons(notifList)
         return root
     }
 
@@ -80,9 +83,10 @@
 
 class ShadeViewManagerFactory @Inject constructor(
     private val logger: ShadeViewDifferLogger,
-    private val viewBarn: NotifViewBarn
+    private val viewBarn: NotifViewBarn,
+    private val notificationIconAreaController: NotificationIconAreaController
 ) {
     fun create(listContainer: NotificationListContainer): ShadeViewManager {
-        return ShadeViewManager(listContainer, logger, viewBarn)
+        return ShadeViewManager(listContainer, logger, viewBarn, notificationIconAreaController)
     }
 }
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 d2f8a39..7ecc036 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
@@ -150,7 +150,6 @@
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -500,7 +499,6 @@
     private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
     private int mHeadsUpInset;
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
-    private NotificationIconAreaController mIconAreaController;
     private final NotificationLockscreenUserManager mLockscreenUserManager;
     private final Rect mTmpRect = new Rect();
     private final FeatureFlags mFeatureFlags;
@@ -5596,11 +5594,6 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public void setIconAreaController(NotificationIconAreaController controller) {
-        mIconAreaController = controller;
-    }
-
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     @VisibleForTesting
     void clearNotifications(
             @SelectedRows int selection,
@@ -5790,10 +5783,6 @@
         mNotificationPanelController = notificationPanelViewController;
     }
 
-    public void updateIconAreaViews() {
-        mIconAreaController.updateNotificationIcons();
-    }
-
     /**
      * Set how far the wake up is when waking up from pulsing. This is a height and will adjust the
      * notification positions accordingly.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 53d3b75..247f2ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -42,7 +42,6 @@
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -479,10 +478,6 @@
         mView.updateFooter();
     }
 
-    public void updateIconAreaViews() {
-        mView.updateIconAreaViews();
-    }
-
     public void onUpdateRowStates() {
         mView.onUpdateRowStates();
     }
@@ -504,10 +499,6 @@
         mView.setNotificationPanelController(notificationPanelViewController);
     }
 
-    public void setIconAreaController(NotificationIconAreaController controller) {
-        mView.setIconAreaController(controller);
-    }
-
     public void setStatusBar(StatusBar statusBar) {
         mView.setStatusBar(statusBar);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 9525830..7e0e872 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -113,7 +113,8 @@
             NotificationShadeWindowController notificationShadeWindowController,
             NotificationWakeUpCoordinator notificationWakeUpCoordinator,
             LockscreenLockIconController lockscreenLockIconController,
-            AuthController authController) {
+            AuthController authController,
+            NotificationIconAreaController notificationIconAreaController) {
         super();
         mDozeLog = dozeLog;
         mPowerManager = powerManager;
@@ -134,6 +135,7 @@
         mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
         mLockscreenLockIconController = lockscreenLockIconController;
         mAuthController = authController;
+        mNotificationIconAreaController = notificationIconAreaController;
     }
 
     // TODO: we should try to not pass status bar in here if we can avoid it.
@@ -141,13 +143,13 @@
     /**
      * Initialize instance with objects only available later during execution.
      */
-    public void initialize(StatusBar statusBar,
-            NotificationIconAreaController notificationIconAreaController,
+    public void initialize(
+            StatusBar statusBar,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             NotificationShadeWindowViewController notificationShadeWindowViewController,
-            NotificationPanelViewController notificationPanel, View ambientIndicationContainer) {
+            NotificationPanelViewController notificationPanel,
+            View ambientIndicationContainer) {
         mStatusBar = statusBar;
-        mNotificationIconAreaController = notificationIconAreaController;
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mNotificationPanel = notificationPanel;
         mNotificationShadeWindowViewController = notificationShadeWindowViewController;
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 0e413fb..bda35fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -8,7 +8,6 @@
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
@@ -21,6 +20,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.demomode.DemoMode;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.plugins.DarkIconDispatcher;
@@ -34,19 +34,23 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.function.Function;
 
+import javax.inject.Inject;
+
 /**
  * A controller for the space in the status bar to the left of the system icons. This area is
  * normally reserved for notifications.
  */
-public class NotificationIconAreaController implements DarkReceiver,
+@SysUISingleton
+public class NotificationIconAreaController implements
+        DarkReceiver,
         StatusBarStateController.StateListener,
         NotificationWakeUpCoordinator.WakeUpListener,
         DemoMode {
@@ -62,13 +66,14 @@
     private final KeyguardBypassController mBypassController;
     private final DozeParameters mDozeParameters;
     private final BubbleController mBubbleController;
+    private final StatusBarWindowController mStatusBarWindowController;
 
     private int mIconSize;
     private int mIconHPadding;
     private int mIconTint = Color.WHITE;
     private int mCenteredIconTint = Color.WHITE;
 
-    private StatusBar mStatusBar;
+    private List<ListEntry> mNotificationEntries = List.of();
     protected View mNotificationIconArea;
     private NotificationIconContainer mNotificationIcons;
     private NotificationIconContainer mShelfIcons;
@@ -77,8 +82,8 @@
     private NotificationIconContainer mAodIcons;
     private StatusBarIconView mCenteredIconView;
     private final Rect mTintArea = new Rect();
-    private ViewGroup mNotificationScrollLayout;
     private Context mContext;
+
     private final DemoModeController mDemoModeController;
 
     private int mAodIconAppearTranslation;
@@ -95,16 +100,14 @@
             new NotificationListener.NotificationSettingsListener() {
                 @Override
                 public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
-                        mShowLowPriority = !hideSilentStatusIcons;
-                        if (mNotificationScrollLayout != null) {
-                            updateStatusBarIcons();
-                        }
+                    mShowLowPriority = !hideSilentStatusIcons;
+                    updateStatusBarIcons();
                 }
             };
 
+    @Inject
     public NotificationIconAreaController(
             Context context,
-            StatusBar statusBar,
             StatusBarStateController statusBarStateController,
             NotificationWakeUpCoordinator wakeUpCoordinator,
             KeyguardBypassController keyguardBypassController,
@@ -112,8 +115,9 @@
             NotificationListener notificationListener,
             DozeParameters dozeParameters,
             BubbleController bubbleController,
-            DemoModeController demoModeController) {
-        mStatusBar = statusBar;
+            DemoModeController demoModeController,
+            DarkIconDispatcher darkIconDispatcher,
+            StatusBarWindowController statusBarWindowController) {
         mContrastColorUtil = ContrastColorUtil.getInstance(context);
         mContext = context;
         mStatusBarStateController = statusBarStateController;
@@ -124,12 +128,14 @@
         wakeUpCoordinator.addListener(this);
         mBypassController = keyguardBypassController;
         mBubbleController = bubbleController;
-        notificationListener.addNotificationSettingsListener(mSettingsListener);
         mDemoModeController = demoModeController;
         mDemoModeController.addCallback(this);
+        mStatusBarWindowController = statusBarWindowController;
+        notificationListener.addNotificationSettingsListener(mSettingsListener);
 
         initializeNotificationAreaViews(context);
         reloadAodColor();
+        darkIconDispatcher.addDarkReceiver(this);
     }
 
     protected View inflateIconArea(LayoutInflater inflater) {
@@ -146,22 +152,21 @@
         mNotificationIconArea = inflateIconArea(layoutInflater);
         mNotificationIcons = mNotificationIconArea.findViewById(R.id.notificationIcons);
 
-        mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
-
         mCenteredIconArea = layoutInflater.inflate(R.layout.center_icon_area, null);
         mCenteredIcon = mCenteredIconArea.findViewById(R.id.centeredIcon);
-
-        initAodIcons();
     }
 
-    public void initAodIcons() {
+    /**
+     * Called by the StatusBar. The StatusBar passes the NotificationIconContainer which holds
+     * the aod icons.
+     */
+    void setupAodIcons(@NonNull NotificationIconContainer aodIcons) {
         boolean changed = mAodIcons != null;
         if (changed) {
             mAodIcons.setAnimationsEnabled(false);
             mAodIcons.removeAllViews();
         }
-        mAodIcons = mStatusBar.getNotificationShadeWindowView().findViewById(
-                R.id.clock_notification_icon_container);
+        mAodIcons = aodIcons;
         mAodIcons.setOnLockScreen(true);
         updateAodIconsVisibility(false /* animate */);
         updateAnimations();
@@ -199,7 +204,7 @@
     @NonNull
     private FrameLayout.LayoutParams generateIconLayoutParams() {
         return new FrameLayout.LayoutParams(
-                mIconSize + 2 * mIconHPadding, getHeight());
+                mIconSize + 2 * mIconHPadding, mStatusBarWindowController.getStatusBarHeight());
     }
 
     private void reloadDimens(Context context) {
@@ -238,29 +243,17 @@
             mTintArea.set(tintArea);
         }
 
-        if (mNotificationIconArea != null) {
-            if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) {
-                mIconTint = iconTint;
-            }
-        } else {
+        if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) {
             mIconTint = iconTint;
         }
 
-        if (mCenteredIconArea != null) {
-            if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) {
-                mCenteredIconTint = iconTint;
-            }
-        } else {
+        if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) {
             mCenteredIconTint = iconTint;
         }
 
         applyNotificationIconsTint();
     }
 
-    protected int getHeight() {
-        return mStatusBar.getStatusBarHeight();
-    }
-
     protected boolean shouldShowNotificationIcon(NotificationEntry entry,
             boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
             boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon,
@@ -310,11 +303,15 @@
         }
         return true;
     }
-
     /**
      * Updates the notifications with the given list of notifications to display.
      */
-    public void updateNotificationIcons() {
+    public void updateNotificationIcons(List<ListEntry> entries) {
+        mNotificationEntries = entries;
+        updateNotificationIcons();
+    }
+
+    private void updateNotificationIcons() {
         updateStatusBarIcons();
         updateShelfIcons();
         updateCenterIcon();
@@ -391,18 +388,15 @@
             NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority,
             boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia,
             boolean hideCenteredIcon, boolean hidePulsing, boolean onlyShowCenteredIcon) {
-        ArrayList<StatusBarIconView> toShow = new ArrayList<>(
-                mNotificationScrollLayout.getChildCount());
-
+        ArrayList<StatusBarIconView> toShow = new ArrayList<>(mNotificationEntries.size());
         // Filter out ambient notifications and notification children.
-        for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) {
-            View view = mNotificationScrollLayout.getChildAt(i);
-            if (view instanceof ExpandableNotificationRow) {
-                NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry();
-                if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed,
+        for (int i = 0; i < mNotificationEntries.size(); i++) {
+            NotificationEntry entry = mNotificationEntries.get(i).getRepresentativeEntry();
+            if (entry != null && entry.getRow() != null) {
+                if (shouldShowNotificationIcon(entry, showAmbient, showLowPriority, hideDismissed,
                         hideRepliedMessages, hideCurrentMedia, hideCenteredIcon, hidePulsing,
                         onlyShowCenteredIcon)) {
-                    StatusBarIconView iconView = function.apply(ent);
+                    StatusBarIconView iconView = function.apply(entry);
                     if (iconView != null) {
                         toShow.add(iconView);
                     }
@@ -607,13 +601,16 @@
         mAodIconTint = Utils.getColorAttrDefaultColor(mContext,
                 R.attr.wallpaperTextColor);
     }
+
     private void updateAodIconColors() {
-        for (int i = 0; i < mAodIcons.getChildCount(); i++) {
-            final StatusBarIconView iv = (StatusBarIconView) mAodIcons.getChildAt(i);
-            if (iv.getWidth() != 0) {
-                updateTintForIcon(iv, mAodIconTint);
-            } else {
-                iv.executeOnLayout(() -> updateTintForIcon(iv, mAodIconTint));
+        if (mAodIcons != null) {
+            for (int i = 0; i < mAodIcons.getChildCount(); i++) {
+                final StatusBarIconView iv = (StatusBarIconView) mAodIcons.getChildAt(i);
+                if (iv.getWidth() != 0) {
+                    updateTintForIcon(iv, mAodIconTint);
+                } else {
+                    iv.executeOnLayout(() -> updateTintForIcon(iv, mAodIconTint));
+                }
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 42fbe59..5974a53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -100,6 +100,7 @@
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -177,6 +178,7 @@
     private final ConfigurationController mConfigurationController;
     private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
     private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
+    private final NotificationIconAreaController mNotificationIconAreaController;
 
     // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
     // changed.
@@ -502,7 +504,8 @@
             BiometricUnlockController biometricUnlockController,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             Provider<KeyguardClockSwitchController> keyguardClockSwitchControllerProvider,
-            NotificationStackScrollLayoutController notificationStackScrollLayoutController) {
+            NotificationStackScrollLayoutController notificationStackScrollLayoutController,
+            NotificationIconAreaController notificationIconAreaController) {
         super(view, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
                 latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
@@ -516,6 +519,7 @@
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mKeyguardClockSwitchControllerProvider = keyguardClockSwitchControllerProvider;
         mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
+        mNotificationIconAreaController = notificationIconAreaController;
         mView.setWillNotDraw(!DEBUG);
         mInjectionInflationController = injectionInflationController;
         mFalsingManager = falsingManager;
@@ -3066,7 +3070,19 @@
         mNotificationStackScrollLayoutController.updateSpeedBumpIndex();
         mNotificationStackScrollLayoutController.updateFooter();
         updateShowEmptyShadeView();
-        mNotificationStackScrollLayoutController.updateIconAreaViews();
+        mNotificationIconAreaController.updateNotificationIcons(createVisibleEntriesList());
+    }
+
+    private List<ListEntry> createVisibleEntriesList() {
+        List<ListEntry> entries = new ArrayList<>(
+                mNotificationStackScrollLayoutController.getChildCount());
+        for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) {
+            View view = mNotificationStackScrollLayoutController.getChildAt(i);
+            if (view instanceof ExpandableNotificationRow) {
+                entries.add(((ExpandableNotificationRow) view).getEntry());
+            }
+        }
+        return entries;
     }
 
     public void onUpdateRowStates() {
@@ -3094,15 +3110,17 @@
         mNotificationStackScrollLayoutController.setScrollingEnabled(b);
     }
 
-    public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager,
+    /**
+     * Initialize objects instead of injecting to avoid circular dependencies.
+     */
+    public void initDependencies(
+            StatusBar statusBar,
+            NotificationGroupManager groupManager,
             NotificationShelfController notificationShelfController,
-            NotificationIconAreaController notificationIconAreaController,
             ScrimController scrimController) {
         setStatusBar(statusBar);
         setGroupManager(mGroupManager);
         mNotificationStackScrollLayoutController.setNotificationPanelController(this);
-        mNotificationStackScrollLayoutController
-                .setIconAreaController(notificationIconAreaController);
         mNotificationStackScrollLayoutController.setStatusBar(statusBar);
         mNotificationStackScrollLayoutController.setGroupManager(groupManager);
         mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
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 5b251be..a0914e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -144,7 +144,6 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIFactory;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.bubbles.BubbleController;
@@ -396,7 +395,7 @@
     private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
     private final LightsOutNotifController mLightsOutNotifController;
     private final InitController mInitController;
-    private final DarkIconDispatcher mDarkIconDispatcher;
+
     private final PluginDependencyProvider mPluginDependencyProvider;
     private final KeyguardDismissUtil mKeyguardDismissUtil;
     private final ExtensionController mExtensionController;
@@ -609,7 +608,7 @@
     private UiModeManager mUiModeManager;
     protected boolean mIsKeyguard;
     private LogMaker mStatusBarStateLog;
-    protected NotificationIconAreaController mNotificationIconAreaController;
+    protected final NotificationIconAreaController mNotificationIconAreaController;
     @Nullable private View mAmbientIndicationContainer;
     private final SysuiColorExtractor mColorExtractor;
     private final ScreenLifecycle mScreenLifecycle;
@@ -731,7 +730,6 @@
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             ViewMediatorCallback viewMediatorCallback,
             InitController initController,
-            DarkIconDispatcher darkIconDispatcher,
             @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
             PluginDependencyProvider pluginDependencyProvider,
             KeyguardDismissUtil keyguardDismissUtil,
@@ -742,7 +740,8 @@
             DismissCallbackRegistry dismissCallbackRegistry,
             DemoModeController demoModeController,
             Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
-            StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager,
+            NotificationIconAreaController notificationIconAreaController) {
         super(context);
         mNotificationsController = notificationsController;
         mLightBarController = lightBarController;
@@ -812,7 +811,6 @@
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mKeyguardViewMediatorCallback = viewMediatorCallback;
         mInitController = initController;
-        mDarkIconDispatcher = darkIconDispatcher;
         mPluginDependencyProvider = pluginDependencyProvider;
         mKeyguardDismissUtil = keyguardDismissUtil;
         mExtensionController = extensionController;
@@ -820,6 +818,7 @@
         mIconPolicy = phoneStatusBarPolicy;
         mDismissCallbackRegistry = dismissCallbackRegistry;
         mDemoModeController = demoModeController;
+        mNotificationIconAreaController = notificationIconAreaController;
 
         mBubbleExpandListener =
                 (isExpanding, key) -> {
@@ -953,9 +952,12 @@
         startKeyguard();
 
         mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
-        mDozeServiceHost.initialize(this, mNotificationIconAreaController,
-                mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController,
-                mNotificationPanelViewController, mAmbientIndicationContainer);
+        mDozeServiceHost.initialize(
+                this,
+                mStatusBarKeyguardViewManager,
+                mNotificationShadeWindowViewController,
+                mNotificationPanelViewController,
+                mAmbientIndicationContainer);
 
         mConfigurationController.addCallback(this);
 
@@ -1037,20 +1039,12 @@
                 mStackScrollerController.getNotificationListContainer();
         mNotificationLogger.setUpWithContainer(notifListContainer);
 
-        // TODO: make this injectable. Currently that would create a circular dependency between
-        // NotificationIconAreaController and StatusBar.
-        mNotificationIconAreaController = SystemUIFactory.getInstance()
-                .createNotificationIconAreaController(context, this,
-                        mWakeUpCoordinator, mKeyguardBypassController,
-                        mStatusBarStateController, mDemoModeController);
-        mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController);
+        updateAodIconArea();
         inflateShelf();
         mNotificationIconAreaController.setupShelf(mNotificationShelfController);
-        mNotificationPanelViewController.setOnReinflationListener(
-                mNotificationIconAreaController::initAodIcons);
+        mNotificationPanelViewController.setOnReinflationListener(this::updateAodIconArea);
         mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
 
-        mDarkIconDispatcher.addDarkReceiver(mNotificationIconAreaController);
         // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
         mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
         mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
@@ -1163,9 +1157,11 @@
         });
         mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble);
 
-        mNotificationPanelViewController.initDependencies(this, mGroupManager,
+        mNotificationPanelViewController.initDependencies(
+                this,
+                mGroupManager,
                 mNotificationShelfController,
-                mNotificationIconAreaController, mScrimController);
+                mScrimController);
 
         BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
         mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
@@ -1279,6 +1275,12 @@
         ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
     }
 
+    private void updateAodIconArea() {
+        mNotificationIconAreaController.setupAodIcons(
+                getNotificationShadeWindowView()
+                        .findViewById(R.id.clock_notification_icon_container));
+    }
+
     @NonNull
     @Override
     public Lifecycle getLifecycle() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index bdf63c79..2355bc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -41,7 +41,6 @@
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.recents.Recents;
@@ -82,6 +81,7 @@
 import com.android.systemui.statusbar.phone.LockscreenLockIconController;
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -189,7 +189,6 @@
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             ViewMediatorCallback viewMediatorCallback,
             InitController initController,
-            DarkIconDispatcher darkIconDispatcher,
             @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
             PluginDependencyProvider pluginDependencyProvider,
             KeyguardDismissUtil keyguardDismissUtil,
@@ -200,7 +199,8 @@
             DemoModeController demoModeController,
             Lazy<NotificationShadeDepthController> notificationShadeDepthController,
             DismissCallbackRegistry dismissCallbackRegistry,
-            StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager,
+            NotificationIconAreaController notificationIconAreaController) {
         return new StatusBar(
                 context,
                 notificationsController,
@@ -268,7 +268,6 @@
                 statusBarKeyguardViewManager,
                 viewMediatorCallback,
                 initController,
-                darkIconDispatcher,
                 timeTickHandler,
                 pluginDependencyProvider,
                 keyguardDismissUtil,
@@ -279,6 +278,7 @@
                 dismissCallbackRegistry,
                 demoModeController,
                 notificationShadeDepthController,
-                statusBarTouchableRegionManager);
+                statusBarTouchableRegionManager,
+                notificationIconAreaController);
     }
 }
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 fec4677..03263db 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
@@ -239,7 +239,6 @@
         mStackScroller.setScrimController(mock(ScrimController.class));
         mStackScroller.setGroupManager(mGroupManager);
         mStackScroller.setEmptyShadeView(mEmptyShadeView);
-        mStackScroller.setIconAreaController(mNotificationIconAreaController);
 
         // Stub out functionality that isn't necessary to test.
         doNothing().when(mBar)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
index 713a7c9..2bcdda4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -102,11 +102,14 @@
                 mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController,
                 mKeyguardUpdateMonitor, mVisualStabilityManager, mPulseExpansionHandler,
                 mNotificationShadeWindowController, mNotificationWakeUpCoordinator,
-                mLockscreenLockIconController, mAuthController);
+                mLockscreenLockIconController, mAuthController, mNotificationIconAreaController);
 
-        mDozeServiceHost.initialize(mStatusBar, mNotificationIconAreaController,
-                mStatusBarKeyguardViewManager, mNotificationShadeWindowViewController,
-                mNotificationPanel, mAmbientIndicationContainer);
+        mDozeServiceHost.initialize(
+                mStatusBar,
+                mStatusBarKeyguardViewManager,
+                mNotificationShadeWindowViewController,
+                mNotificationPanel,
+                mAmbientIndicationContainer);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index 18cb667..5222fff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -17,7 +17,6 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -29,10 +28,12 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,8 +49,6 @@
     @Mock
     private NotificationListener mListener;
     @Mock
-    StatusBar mStatusBar;
-    @Mock
     StatusBarStateController mStatusBarStateController;
     @Mock
     NotificationWakeUpCoordinator mWakeUpCoordinator;
@@ -58,28 +57,37 @@
     @Mock
     NotificationMediaManager mNotificationMediaManager;
     @Mock
-    NotificationIconContainer mNotificationIconContainer;
-    @Mock
     DozeParameters mDozeParameters;
     @Mock
-    NotificationShadeWindowView mNotificationShadeWindowView;
+    CommonNotifCollection mNotifCollection;
+    @Mock
+    DarkIconDispatcher mDarkIconDispatcher;
+    @Mock
+    StatusBarWindowController mStatusBarWindowController;
     private NotificationIconAreaController mController;
     @Mock
     private BubbleController mBubbleController;
     @Mock private DemoModeController mDemoModeController;
+    @Mock
+    private NotificationIconContainer mAodIcons;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
 
-        when(mStatusBar.getNotificationShadeWindowView()).thenReturn(mNotificationShadeWindowView);
-        when(mNotificationShadeWindowView.findViewById(anyInt())).thenReturn(
-                mNotificationIconContainer);
-
-        mController = new NotificationIconAreaController(mContext, mStatusBar,
-                mStatusBarStateController, mWakeUpCoordinator, mKeyguardBypassController,
-                mNotificationMediaManager, mListener, mDozeParameters, mBubbleController,
-                mDemoModeController);
+        mController = new NotificationIconAreaController(
+                mContext,
+                mStatusBarStateController,
+                mWakeUpCoordinator,
+                mKeyguardBypassController,
+                mNotificationMediaManager,
+                mListener,
+                mDozeParameters,
+                mBubbleController,
+                mDemoModeController,
+                mDarkIconDispatcher,
+                mStatusBarWindowController);
+        mController.setupAodIcons(mAodIcons);
     }
 
     @Test
@@ -100,7 +108,7 @@
     public void testAppearResetsTranslation() {
         when(mDozeParameters.shouldControlScreenOff()).thenReturn(false);
         mController.appearAodIcons();
-        verify(mNotificationIconContainer).setTranslationY(0);
-        verify(mNotificationIconContainer).setAlpha(1.0f);
+        verify(mAodIcons).setTranslationY(0);
+        verify(mAodIcons).setAlpha(1.0f);
     }
 }
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 a0c0e79..c9e9d94 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
@@ -251,9 +251,13 @@
                 mConversationNotificationManager, mMediaHiearchyManager,
                 mBiometricUnlockController, mStatusBarKeyguardViewManager,
                 () -> mKeyguardClockSwitchController,
-                mNotificationStackScrollLayoutController);
-        mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
-                mNotificationShelfController, mNotificationAreaController, mScrimController);
+                mNotificationStackScrollLayoutController,
+                mNotificationAreaController);
+        mNotificationPanelViewController.initDependencies(
+                mStatusBar,
+                mGroupManager,
+                mNotificationShelfController,
+                mScrimController);
         mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
         mNotificationPanelViewController.setBar(mPanelBar);
 
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 8a1d95ea4..cb9f50d 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
@@ -405,7 +405,6 @@
                 mStatusBarKeyguardViewManager,
                 mViewMediatorCallback,
                 mInitController,
-                mDarkIconDispatcher,
                 new Handler(TestableLooper.get(this).getLooper()),
                 mPluginDependencyProvider,
                 mKeyguardDismissUtil,
@@ -416,7 +415,8 @@
                 mDismissCallbackRegistry,
                 mDemoModeController,
                 mNotificationShadeDepthControllerLazy,
-                mStatusBarTouchableRegionManager);
+                mStatusBarTouchableRegionManager,
+                mNotificationIconAreaController);
 
         when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
                 mLockIconContainer);
@@ -434,7 +434,6 @@
         mStatusBar.mNotificationShadeWindowView = mNotificationShadeWindowView;
         mStatusBar.mNotificationPanelViewController = mNotificationPanelViewController;
         mStatusBar.mDozeScrimController = mDozeScrimController;
-        mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController;
         mStatusBar.mPresenter = mNotificationPresenter;
         mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController;
         mStatusBar.mBarService = mBarService;