[Status Bar Refactor] Move LightsOutNotifController to the
FragmentComponent since it effectively gets re-created each time we
create a new status bar view.

Test: manual (verified controller was re-created each time SBV was
re-created and verified only one controller was active at a time)
Test: LightsOutNotifControllerTest
Bug: 209005990
Bug: 205609837

Change-Id: Idd80cf6461512a7e3e8a3b15667898991eef9e72
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 68ab077..c09cca1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
@@ -18,6 +18,8 @@
 
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
 
+import static com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentModule.LIGHTS_OUT_NOTIF_VIEW;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.Nullable;
@@ -31,13 +33,15 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.view.AppearanceRegion;
-import com.android.systemui.dagger.SysUISingleton;
 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.NotificationEntry;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
+import com.android.systemui.util.ViewController;
 
 import javax.inject.Inject;
+import javax.inject.Named;
 
 /**
  * Apps can request a low profile mode {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}
@@ -47,8 +51,8 @@
  * This controller shows and hides the notification dot in the status bar to indicate
  * whether there are notifications when the device is in {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}.
  */
-@SysUISingleton
-public class LightsOutNotifController {
+@StatusBarFragmentScope
+public class LightsOutNotifController extends ViewController<View> {
     private final CommandQueue mCommandQueue;
     private final NotificationEntryManager mEntryManager;
     private final WindowManager mWindowManager;
@@ -57,40 +61,31 @@
     @VisibleForTesting @Appearance int mAppearance;
 
     private int mDisplayId;
-    private View mLightsOutNotifView;
 
     @Inject
-    LightsOutNotifController(WindowManager windowManager,
+    LightsOutNotifController(
+            @Named(LIGHTS_OUT_NOTIF_VIEW) View lightsOutNotifView,
+            WindowManager windowManager,
             NotificationEntryManager entryManager,
             CommandQueue commandQueue) {
+        super(lightsOutNotifView);
         mWindowManager = windowManager;
         mEntryManager = entryManager;
         mCommandQueue = commandQueue;
+
     }
 
-    /**
-     * Sets the notification dot view after it is created in the StatusBar.
-     * This is the view this controller will show and hide depending on whether:
-     * 1. there are active notifications
-     * 2. an app has requested {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}
-     */
-    void setLightsOutNotifView(View lightsOutNotifView) {
-        destroy();
-        mLightsOutNotifView = lightsOutNotifView;
-
-        if (mLightsOutNotifView != null) {
-            mLightsOutNotifView.setVisibility(View.GONE);
-            mLightsOutNotifView.setAlpha(0f);
-            init();
-        }
-    }
-
-    private void destroy() {
+    @Override
+    protected void onViewDetached() {
         mEntryManager.removeNotificationEntryListener(mEntryListener);
         mCommandQueue.removeCallback(mCallback);
     }
 
-    private void init() {
+    @Override
+    protected void onViewAttached() {
+        mView.setVisibility(View.GONE);
+        mView.setAlpha(0f);
+
         mDisplayId = mWindowManager.getDefaultDisplay().getDisplayId();
         mEntryManager.addNotificationEntryListener(mEntryListener);
         mCommandQueue.addCallback(mCallback);
@@ -104,29 +99,25 @@
 
     @VisibleForTesting
     void updateLightsOutView() {
-        if (mLightsOutNotifView == null) {
-            return;
-        }
-
         final boolean showDot = shouldShowDot();
         if (showDot != isShowingDot()) {
             if (showDot) {
-                mLightsOutNotifView.setAlpha(0f);
-                mLightsOutNotifView.setVisibility(View.VISIBLE);
+                mView.setAlpha(0f);
+                mView.setVisibility(View.VISIBLE);
             }
 
-            mLightsOutNotifView.animate()
+            mView.animate()
                     .alpha(showDot ? 1 : 0)
                     .setDuration(showDot ? 750 : 250)
                     .setInterpolator(new AccelerateInterpolator(2.0f))
                     .setListener(new AnimatorListenerAdapter() {
                         @Override
                         public void onAnimationEnd(Animator a) {
-                            mLightsOutNotifView.setAlpha(showDot ? 1 : 0);
-                            mLightsOutNotifView.setVisibility(showDot ? View.VISIBLE : View.GONE);
+                            mView.setAlpha(showDot ? 1 : 0);
+                            mView.setVisibility(showDot ? View.VISIBLE : View.GONE);
                             // Unset the listener, otherwise this may persist for
                             // another view property animation
-                            mLightsOutNotifView.animate().setListener(null);
+                            mView.animate().setListener(null);
                         }
                     })
                     .start();
@@ -135,8 +126,8 @@
 
     @VisibleForTesting
     boolean isShowingDot() {
-        return mLightsOutNotifView.getVisibility() == View.VISIBLE
-                && mLightsOutNotifView.getAlpha() == 1.0f;
+        return mView.getVisibility() == View.VISIBLE
+                && mView.getAlpha() == 1.0f;
     }
 
     @VisibleForTesting
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 84ef079..5e1f048 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -499,7 +499,6 @@
     private final StatusBarNotificationActivityStarter.Builder
             mStatusBarNotificationActivityStarterBuilder;
     private final ShadeController mShadeController;
-    private final LightsOutNotifController mLightsOutNotifController;
     private final InitController mInitController;
 
     private final PluginDependencyProvider mPluginDependencyProvider;
@@ -756,7 +755,6 @@
             StatusBarComponent.Factory statusBarComponentFactory,
             PluginManager pluginManager,
             Optional<LegacySplitScreen> splitScreenOptional,
-            LightsOutNotifController lightsOutNotifController,
             StatusBarNotificationActivityStarter.Builder
                     statusBarNotificationActivityStarterBuilder,
             ShadeController shadeController,
@@ -863,7 +861,6 @@
         mSplitScreenOptional = splitScreenOptional;
         mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder;
         mShadeController = shadeController;
-        mLightsOutNotifController =  lightsOutNotifController;
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mKeyguardViewMediatorCallback = viewMediatorCallback;
         mInitController = initController;
@@ -1166,9 +1163,6 @@
                     // displayed).
                     mNotificationPanelViewController.updatePanelExpansionAndVisibility();
                     setBouncerShowingForStatusBarComponents(mBouncerShowing);
-
-                    mLightsOutNotifController.setLightsOutNotifView(
-                            mStatusBarView.findViewById(R.id.notification_lights_out));
                     mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView);
                     checkBarModes();
                 }).getFragmentManager()
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 33171b2..83613ac 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
@@ -85,7 +85,6 @@
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.LightsOutNotifController;
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
@@ -205,7 +204,6 @@
             StatusBarComponent.Factory statusBarComponentFactory,
             PluginManager pluginManager,
             Optional<LegacySplitScreen> splitScreenOptional,
-            LightsOutNotifController lightsOutNotifController,
             StatusBarNotificationActivityStarter.Builder
                     statusBarNotificationActivityStarterBuilder,
             ShadeController shadeController,
@@ -308,7 +306,6 @@
                 statusBarComponentFactory,
                 pluginManager,
                 splitScreenOptional,
-                lightsOutNotifController,
                 statusBarNotificationActivityStarterBuilder,
                 shadeController,
                 statusBarKeyguardViewManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
index 3656ed1..9dfbe88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
@@ -19,6 +19,7 @@
 import com.android.systemui.battery.BatteryMeterViewController;
 import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.LightsOutNotifController;
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
 import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
@@ -55,11 +56,12 @@
      * Initialize anything extra for the component. Must be called after the component is created.
      */
     default void init() {
-        // No one accesses this controller, so we need to make sure we reference it here so it does
-        // get initialized.
+        // No one accesses these controllers, so we need to make sure we reference them here so they
+        // do get initialized.
         getBatteryMeterViewController().init();
         getHeadsUpAppearanceController().init();
         getPhoneStatusBarViewController().init();
+        getLightsOutNotifController().init();
     }
 
     /** */
@@ -78,4 +80,8 @@
     /** */
     @StatusBarFragmentScope
     HeadsUpAppearanceController getHeadsUpAppearanceController();
+
+    /** */
+    @StatusBarFragmentScope
+    LightsOutNotifController getLightsOutNotifController();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
index d244558..f8014fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone.fragment.dagger;
 
+import android.view.View;
+
 import com.android.systemui.R;
 import com.android.systemui.battery.BatteryMeterView;
 import com.android.systemui.dagger.qualifiers.RootView;
@@ -24,12 +26,17 @@
 import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
 import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
 
+import javax.inject.Named;
+
 import dagger.Module;
 import dagger.Provides;
 
 /** Dagger module for {@link StatusBarFragmentComponent}. */
 @Module
 public interface StatusBarFragmentModule {
+
+    String LIGHTS_OUT_NOTIF_VIEW = "lights_out_notif_view";
+
     /** */
     @Provides
     @RootView
@@ -49,6 +56,14 @@
     /** */
     @Provides
     @StatusBarFragmentScope
+    @Named(LIGHTS_OUT_NOTIF_VIEW)
+    static View provideLightsOutNotifView(@RootView PhoneStatusBarView view) {
+        return view.findViewById(R.id.notification_lights_out);
+    }
+
+    /** */
+    @Provides
+    @StatusBarFragmentScope
     static PhoneStatusBarViewController providePhoneStatusBarViewController(
             PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
             @RootView PhoneStatusBarView phoneStatusBarView,
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 74f08ab..e386263 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
@@ -81,9 +81,10 @@
         when(mWindowManager.getDefaultDisplay()).thenReturn(mDisplay);
         when(mDisplay.getDisplayId()).thenReturn(mDisplayId);
 
-        mLightsOutNotifController = new LightsOutNotifController(mWindowManager, mEntryManager,
-                mCommandQueue);
-        mLightsOutNotifController.setLightsOutNotifView(mLightsOutView);
+        mLightsOutNotifController = new LightsOutNotifController(
+                mLightsOutView, mWindowManager, mEntryManager, mCommandQueue);
+        mLightsOutNotifController.init();
+        mLightsOutNotifController.onViewAttached();
 
         // Capture the entry listener object so we can simulate events in tests below
         verify(mEntryManager).addNotificationEntryListener(mListenerCaptor.capture());
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 a34d2f5..7cc3042 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
@@ -251,7 +251,6 @@
     @Mock private StatusBarComponent mStatusBarComponent;
     @Mock private PluginManager mPluginManager;
     @Mock private LegacySplitScreen mLegacySplitScreen;
-    @Mock private LightsOutNotifController mLightsOutNotifController;
     @Mock private ViewMediatorCallback mViewMediatorCallback;
     @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     @Mock private ScreenPinningRequest mScreenPinningRequest;
@@ -436,7 +435,6 @@
                 mStatusBarComponentFactory,
                 mPluginManager,
                 Optional.of(mLegacySplitScreen),
-                mLightsOutNotifController,
                 mStatusBarNotificationActivityStarterBuilder,
                 mShadeController,
                 mStatusBarKeyguardViewManager,