Start using some dagger 2

Early days as we start migration, so lots of duplication between
Dependency and dagger2, but can be removed when migration is done.

Test: existing tests.
Change-Id: I00c3da6ebbd46a26e512d8a7aa1e2b828e08f33f
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index 74d6605..293fa9a 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -80,4 +80,5 @@
         "com.android.keyguard",
     ],
 
+    annotation_processors: ["dagger2-compiler-2.19"],
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
index f57f26d..7039a2c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -17,25 +17,42 @@
 package com.android.systemui;
 
 import android.content.Context;
-import android.util.ArrayMap;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.Dependency.DependencyProvider;
 import com.android.systemui.car.CarNotificationEntryManager;
 import com.android.systemui.statusbar.car.CarFacetButtonController;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.car.hvac.HvacController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.volume.CarVolumeDialogComponent;
 import com.android.systemui.volume.VolumeDialogComponent;
 
+import javax.inject.Singleton;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+
 /**
  * Class factory to provide car specific SystemUI components.
  */
 public class CarSystemUIFactory extends SystemUIFactory {
 
+    private CarDependencyComponent mCarDependencyComponent;
+
+    @Override
+    protected void init(Context context) {
+        super.init(context);
+        mCarDependencyComponent = DaggerCarSystemUIFactory_CarDependencyComponent.builder()
+                .contextHolder(new ContextHolder(context))
+                .build();
+    }
+
+    public CarDependencyComponent getCarDependencyComponent() {
+        return mCarDependencyComponent;
+    }
+
     public StatusBarKeyguardViewManager createStatusBarKeyguardViewManager(Context context,
         ViewMediatorCallback viewMediatorCallback, LockPatternUtils lockPatternUtils) {
         return new CarStatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils);
@@ -46,12 +63,27 @@
     }
 
     @Override
-    public void injectDependencies(ArrayMap<Object, DependencyProvider> providers,
-        Context context) {
-        super.injectDependencies(providers, context);
-        providers.put(NotificationEntryManager.class,
-            () -> new CarNotificationEntryManager(context));
-        providers.put(CarFacetButtonController.class, () -> new CarFacetButtonController(context));
-        providers.put(HvacController.class, () -> new HvacController(context));
+    public NotificationEntryManager provideNotificationEntryManager(Context context) {
+        return new CarNotificationEntryManager(context);
+    }
+
+    @Module
+    protected static class ContextHolder {
+        private Context mContext;
+
+        public ContextHolder(Context context) {
+            mContext = context;
+        }
+
+        @Provides
+        public Context provideContext() {
+            return mContext;
+        }
+    }
+
+    @Singleton
+    @Component(modules = ContextHolder.class)
+    public interface CarDependencyComponent {
+        CarFacetButtonController getCarFacetButtonController();
     }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index cea4ab0..0a20eaa 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -26,8 +26,9 @@
 import android.widget.LinearLayout;
 
 import com.android.keyguard.AlphaOptimizedImageButton;
-import com.android.systemui.Dependency;
+import com.android.systemui.CarSystemUIFactory;
 import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
 
 /**
  * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined
@@ -76,8 +77,9 @@
         TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
         setupIntents(typedArray);
         setupIcons(typedArray);
-        CarFacetButtonController carFacetButtonController = Dependency.get(
-                CarFacetButtonController.class);
+        CarSystemUIFactory factory = SystemUIFactory.getInstance();
+        CarFacetButtonController carFacetButtonController = factory.getCarDependencyComponent()
+                .getCarFacetButtonController();
         carFacetButtonController.addFacetButton(this);
     }
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
index 56db242..7811a1c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
@@ -29,11 +29,15 @@
 import java.util.List;
 import java.util.Set;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * CarFacetButtons placed on the nav bar are designed to have visual indication that the active
  * application on screen is associated with it. This is basically a similar concept to a radio
  * button group.
  */
+@Singleton
 public class CarFacetButtonController {
 
     protected HashMap<String, CarFacetButton> mButtonsByCategory = new HashMap<>();
@@ -42,6 +46,7 @@
     protected CarFacetButton mSelectedFacetButton;
     protected Context mContext;
 
+    @Inject
     public CarFacetButtonController(Context context) {
         mContext = context;
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 5da236c..7028999c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -29,9 +29,11 @@
 
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.BatteryMeterView;
+import com.android.systemui.CarSystemUIFactory;
 import com.android.systemui.Dependency;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.fragments.FragmentHostManager;
@@ -102,7 +104,9 @@
 
         mHvacController.connectToCarService();
 
-        mCarFacetButtonController = Dependency.get(CarFacetButtonController.class);
+        CarSystemUIFactory factory = SystemUIFactory.getInstance();
+        mCarFacetButtonController = factory.getCarDependencyComponent()
+                .getCarFacetButtonController();
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
         if (!mDeviceIsProvisioned) {
@@ -239,7 +243,7 @@
     @Override
     protected void makeStatusBarView() {
         super.makeStatusBarView();
-        mHvacController = Dependency.get(HvacController.class);
+        mHvacController = new HvacController(mContext);
 
         mNotificationPanelBackground = getDefaultWallpaper();
         mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index ad44b9a..8be67d9 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -115,6 +115,8 @@
         "mockito-target-inline-minus-junit4",
         "testables",
         "truth-prebuilt",
+        "dagger2-2.19",
+        "jsr330"
     ],
     libs: [
         "android.test.runner",
@@ -125,6 +127,7 @@
         "--extra-packages",
         "com.android.keyguard:com.android.systemui",
     ],
+    annotation_processors: ["dagger2-compiler-2.19"],
 }
 
 android_app {
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
new file mode 100644
index 0000000..565d765
--- /dev/null
+++ b/packages/SystemUI/docs/dagger.md
@@ -0,0 +1,136 @@
+# Dagger 2 in SystemUI
+*Dagger 2 is a dependency injection framework that compiles annotations to code
+to create dependencies without reflection*
+
+## Recommended reading
+
+Go read about Dagger 2.
+
+TODO: Add some links.
+
+## State of the world
+
+Dagger 2 has been turned on for SystemUI and a early first pass has been taken
+for converting everything in Dependency.java to use Dagger. Since a lot of
+SystemUI depends on Dependency, stubs have been added to Dependency to proxy
+any gets through to the instances provided by dagger, this will allow migration
+of SystemUI through a number of CLs.
+
+### How it works in SystemUI
+
+For the classes that we're using in Dependency and are switching to dagger, the
+equivalent dagger version is using @Singleton and only having one instance.
+To have the single instance span all of SystemUI and be easily accessible for
+other components, there is a single root Component that exists that generates
+these. The component lives in SystemUIFactory and is called SystemUIRootComponent.
+
+```java
+@Singleton
+@Component(modules = {SystemUIFactory.class, DependencyProvider.class, ContextHolder.class})
+public interface SystemUIRootComponent {
+    @Singleton
+    Dependency.DependencyInjector createDependency();
+}
+```
+
+The root modules are what provides the global singleton dependencies across
+SystemUI. ContextHolder is just a wrapper that provides a context.
+SystemUIFactory @Provide dependencies that need to be overridden by SystemUI
+variants (like other form factors). DependencyProvider provides or binds any
+remaining depedencies required.
+
+### Adding injection to a new SystemUI object
+
+Anything that depends on any @Singleton provider from SystemUIRootComponent
+should be declared as a Subcomponent of the root component, this requires
+declaring your own interface for generating your own modules or just the
+object you need injected. The subcomponent also needs to be added to
+SystemUIRootComponent in SystemUIFactory so it can be acquired.
+
+```java
+public interface SystemUIRootComponent {
++    @Singleton
++    Dependency.DependencyInjector createDependency();
+}
+
+public class Dependency extends SystemUI {
+  ...
++  @Subcomponent
++  public interface DependencyInjector {
++      Dependency createSystemUI();
++  }
+}
+```
+
+For objects that extend SystemUI and require injection, you can define an
+injector that creates the injected object for you. This other class should
+be referenced in @string/config_systemUIServiceComponents.
+
+```java
+public static class DependencyCreator implements Injector {
+    @Override
+    public SystemUI apply(Context context) {
+        return SystemUIFactory.getInstance().getRootComponent()
+                .createDependency()
+                .createSystemUI();
+    }
+}
+```
+
+### Adding a new injectable object
+
+First tag the constructor with @Inject. Also tag it with @Singleton if only one
+instance should be created.
+
+```java
+@Singleton
+public class SomethingController {
+  @Inject
+  public SomethingController(Context context,
+    @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+      // context and mainHandler will be automatically populated.
+  }
+}
+```
+
+If you have an interface class and an implementation class, dagger needs to know
+how to map it. The simplest way to do this is to add a provides method to
+DependencyProvider.
+
+```java
+public class DependencyProvider {
+  ...
+  @Singleton
+  @Provide
+  public SomethingController provideSomethingController(Context context,
+      @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+    return new SomethingControllerImpl(context, mainHandler);
+  }
+}
+```
+
+If you need to access this from Dependency#get, then add an adapter to Dependency
+that maps to the instance provided by Dagger. The changes should be similar
+to the following diff.
+
+```java
+public class Dependency {
+  ...
+  @Inject Lazy<SomethingController> mSomethingController;
+  ...
+  public void start() {
+    ...
+    mProviders.put(SomethingController.class, mSomethingController::get);
+  }
+}
+```
+
+## TODO List
+
+ - Eliminate usages of Depndency#get
+ - Add support for Fragments to handle injection automatically
+   - (this could be through dagger2-android or something custom)
+ - Reduce number of things with @Provide in DependencyProvider (many can be
+   @Inject instead)
+ - Migrate as many remaining DependencyProvider instances to @Bind
+ - Add links in above TODO
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index ee94aed..cc6848f 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -17,6 +17,7 @@
 -keep class com.android.systemui.car.CarSystemUIFactory
 -keep class com.android.systemui.SystemUIFactory
 -keep class * extends com.android.systemui.SystemUI
+-keep class * implements com.android.systemui.SystemUI$Injector
 
 -keepclasseswithmembers class * {
     public <init>(android.content.Context, android.util.AttributeSet);
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 61efbd5..889db66 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -290,7 +290,7 @@
 
     <!-- SystemUI Services: The classes of the stuff to start. -->
     <string-array name="config_systemUIServiceComponents" translatable="false">
-        <item>com.android.systemui.Dependency</item>
+        <item>com.android.systemui.Dependency$DependencyCreator</item>
         <item>com.android.systemui.util.NotificationChannels</item>
         <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
         <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
@@ -318,7 +318,7 @@
 
     <!-- SystemUI Services (per user): The classes of the stuff to start for each user. This is a subset of the config_systemUIServiceComponents -->
     <string-array name="config_systemUIServiceComponentsPerUser" translatable="false">
-        <item>com.android.systemui.Dependency</item>
+        <item>com.android.systemui.Dependency$DependencyCreator</item>
         <item>com.android.systemui.util.NotificationChannels</item>
     </string-array>
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 327ffcd..4e5af15 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -14,20 +14,15 @@
 
 package com.android.systemui;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.hardware.SensorManager;
 import android.hardware.SensorPrivacyManager;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
-import android.os.Process;
-import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.view.IWindowManager;
-import android.view.WindowManagerGlobal;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ColorDisplayController;
@@ -36,92 +31,86 @@
 import com.android.internal.util.Preconditions;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.appops.AppOpsControllerImpl;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.PluginDependencyProvider;
-import com.android.systemui.plugins.PluginInitializerImpl;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.power.EnhancedEstimates;
-import com.android.systemui.power.EnhancedEstimatesImpl;
-import com.android.systemui.power.PowerNotificationWarnings;
 import com.android.systemui.power.PowerUI;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.shared.plugins.PluginManagerImpl;
+import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.DisplayNavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
-import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
-import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
-import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
-import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
+import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ShadeController;
-import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BatteryControllerImpl;
 import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
 import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.CastControllerImpl;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
 import com.android.systemui.statusbar.policy.ExtensionController;
-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.HotspotController;
-import com.android.systemui.statusbar.policy.HotspotControllerImpl;
 import com.android.systemui.statusbar.policy.IconLogger;
-import com.android.systemui.statusbar.policy.IconLoggerImpl;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
 import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationControllerImpl;
 import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
 import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.SecurityControllerImpl;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
 import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
 import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
 import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerServiceImpl;
 import com.android.systemui.util.AsyncSensorManager;
 import com.android.systemui.util.leak.GarbageMonitor;
 import com.android.systemui.util.leak.LeakDetector;
 import com.android.systemui.util.leak.LeakReporter;
-import com.android.systemui.volume.VolumeDialogControllerImpl;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.function.Consumer;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import dagger.Lazy;
+import dagger.Subcomponent;
+
 /**
  * Class to handle ugly dependencies throughout sysui until we determine the
  * long-term dependency injection solution.
@@ -143,235 +132,302 @@
     /**
      * Key for getting a background Looper for background work.
      */
-    public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>("background_looper");
+    public static final String BG_LOOPER_NAME = "background_looper";
     /**
      * Key for getting a background Handler for background work.
      */
-    public static final DependencyKey<Handler> BG_HANDLER = new DependencyKey<>("background_handler");
+    public static final String BG_HANDLER_NAME = "background_handler";
     /**
      * Key for getting a Handler for receiving time tick broadcasts on.
      */
-    public static final DependencyKey<Handler> TIME_TICK_HANDLER =
-            new DependencyKey<>("time_tick_handler");
+    public static final String TIME_TICK_HANDLER_NAME = "time_tick_handler";
     /**
      * Generic handler on the main thread.
      */
-    public static final DependencyKey<Handler> MAIN_HANDLER = new DependencyKey<>("main_handler");
+    public static final String MAIN_HANDLER_NAME = "main_handler";
 
     /**
      * An email address to send memory leak reports to by default.
      */
-    public static final DependencyKey<String> LEAK_REPORT_EMAIL
-            = new DependencyKey<>("leak_report_email");
+    public static final String LEAK_REPORT_EMAIL_NAME = "leak_report_email";
+
+    /**
+     * Key for getting a background Looper for background work.
+     */
+    public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>(BG_LOOPER_NAME);
+    /**
+     * Key for getting a background Handler for background work.
+     */
+    public static final DependencyKey<Handler> BG_HANDLER = new DependencyKey<>(BG_HANDLER_NAME);
+    /**
+     * Key for getting a Handler for receiving time tick broadcasts on.
+     */
+    public static final DependencyKey<Handler> TIME_TICK_HANDLER =
+            new DependencyKey<>(TIME_TICK_HANDLER_NAME);
+    /**
+     * Generic handler on the main thread.
+     */
+    public static final DependencyKey<Handler> MAIN_HANDLER =
+            new DependencyKey<>(MAIN_HANDLER_NAME);
+
+    /**
+     * An email address to send memory leak reports to by default.
+     */
+    public static final DependencyKey<String> LEAK_REPORT_EMAIL =
+            new DependencyKey<>(LEAK_REPORT_EMAIL_NAME);
 
     private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();
     private final ArrayMap<Object, DependencyProvider> mProviders = new ArrayMap<>();
 
+    @Inject Lazy<ActivityStarter> mActivityStarter;
+    @Inject Lazy<ActivityStarterDelegate> mActivityStarterDelegate;
+    @Inject Lazy<AsyncSensorManager> mAsyncSensorManager;
+    @Inject Lazy<BluetoothController> mBluetoothController;
+    @Inject Lazy<LocationController> mLocationController;
+    @Inject Lazy<RotationLockController> mRotationLockController;
+    @Inject Lazy<NetworkController> mNetworkController;
+    @Inject Lazy<ZenModeController> mZenModeController;
+    @Inject Lazy<HotspotController> mHotspotController;
+    @Inject Lazy<CastController> mCastController;
+    @Inject Lazy<FlashlightController> mFlashlightController;
+    @Inject Lazy<UserSwitcherController> mUserSwitcherController;
+    @Inject Lazy<UserInfoController> mUserInfoController;
+    @Inject Lazy<KeyguardMonitor> mKeyguardMonitor;
+    @Inject Lazy<BatteryController> mBatteryController;
+    @Inject Lazy<ColorDisplayController> mColorDisplayController;
+    @Inject Lazy<ManagedProfileController> mManagedProfileController;
+    @Inject Lazy<NextAlarmController> mNextAlarmController;
+    @Inject Lazy<DataSaverController> mDataSaverController;
+    @Inject Lazy<AccessibilityController> mAccessibilityController;
+    @Inject Lazy<DeviceProvisionedController> mDeviceProvisionedController;
+    @Inject Lazy<PluginManager> mPluginManager;
+    @Inject Lazy<AssistManager> mAssistManager;
+    @Inject Lazy<SecurityController> mSecurityController;
+    @Inject Lazy<LeakDetector> mLeakDetector;
+    @Inject Lazy<LeakReporter> mLeakReporter;
+    @Inject Lazy<GarbageMonitor> mGarbageMonitor;
+    @Inject Lazy<IconLogger> mIconLogger;
+    @Inject Lazy<TunerService> mTunerService;
+    @Inject Lazy<StatusBarWindowController> mStatusBarWindowController;
+    @Inject Lazy<DarkIconDispatcher> mDarkIconDispatcher;
+    @Inject Lazy<ConfigurationController> mConfigurationController;
+    @Inject Lazy<StatusBarIconController> mStatusBarIconController;
+    @Inject Lazy<ScreenLifecycle> mScreenLifecycle;
+    @Inject Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
+    @Inject Lazy<FragmentService> mFragmentService;
+    @Inject Lazy<ExtensionController> mExtensionController;
+    @Inject Lazy<PluginDependencyProvider> mPluginDependencyProvider;
+    @Inject Lazy<LocalBluetoothManager> mLocalBluetoothManager;
+    @Inject Lazy<VolumeDialogController> mVolumeDialogController;
+    @Inject Lazy<MetricsLogger> mMetricsLogger;
+    @Inject Lazy<AccessibilityManagerWrapper> mAccessibilityManagerWrapper;
+    @Inject Lazy<SysuiColorExtractor> mSysuiColorExtractor;
+    @Inject Lazy<TunablePaddingService> mTunablePaddingService;
+    @Inject Lazy<ForegroundServiceController> mForegroundServiceController;
+    @Inject Lazy<UiOffloadThread> mUiOffloadThread;
+    @Inject Lazy<PowerUI.WarningsUI> mWarningsUI;
+    @Inject Lazy<LightBarController> mLightBarController;
+    @Inject Lazy<IWindowManager> mIWindowManager;
+    @Inject Lazy<OverviewProxyService> mOverviewProxyService;
+    @Inject Lazy<EnhancedEstimates> mEnhancedEstimates;
+    @Inject Lazy<VibratorHelper> mVibratorHelper;
+    @Inject Lazy<IStatusBarService> mIStatusBarService;
+    @Inject Lazy<DisplayMetrics> mDisplayMetrics;
+    @Inject Lazy<LockscreenGestureLogger> mLockscreenGestureLogger;
+    @Inject Lazy<KeyguardEnvironment> mKeyguardEnvironment;
+    @Inject Lazy<ShadeController> mShadeController;
+    @Inject Lazy<NotificationRemoteInputManager.Callback> mNotificationRemoteInputManagerCallback;
+    @Inject Lazy<InitController> mInitController;
+    @Inject Lazy<AppOpsController> mAppOpsController;
+    @Inject Lazy<DisplayNavigationBarController> mDisplayNavigationBarController;
+    @Inject Lazy<StatusBarStateController> mStatusBarStateController;
+    @Inject Lazy<NotificationLockscreenUserManager> mNotificationLockscreenUserManager;
+    @Inject Lazy<NotificationGroupAlertTransferHelper> mNotificationGroupAlertTransferHelper;
+    @Inject Lazy<NotificationGroupManager> mNotificationGroupManager;
+    @Inject Lazy<VisualStabilityManager> mVisualStabilityManager;
+    @Inject Lazy<NotificationGutsManager> mNotificationGutsManager;
+    @Inject Lazy<NotificationMediaManager> mNotificationMediaManager;
+    @Inject Lazy<AmbientPulseManager> mAmbientPulseManager;
+    @Inject Lazy<NotificationBlockingHelperManager> mNotificationBlockingHelperManager;
+    @Inject Lazy<NotificationRemoteInputManager> mNotificationRemoteInputManager;
+    @Inject Lazy<SmartReplyConstants> mSmartReplyConstants;
+    @Inject Lazy<NotificationListener> mNotificationListener;
+    @Inject Lazy<NotificationLogger> mNotificationLogger;
+    @Inject Lazy<NotificationViewHierarchyManager> mNotificationViewHierarchyManager;
+    @Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil;
+    @Inject Lazy<SmartReplyController> mSmartReplyController;
+    @Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler;
+    @Inject Lazy<BubbleController> mBubbleController;
+    @Inject Lazy<NotificationEntryManager> mNotificationEntryManager;
+    @Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
+    @Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper;
+    @Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler;
+    @Inject @Named(MAIN_HANDLER_NAME) Lazy<Handler> mMainHandler;
+    @Inject @Named(TIME_TICK_HANDLER_NAME) Lazy<Handler> mTimeTickHandler;
+    @Nullable
+    @Inject @Named(LEAK_REPORT_EMAIL_NAME) Lazy<String> mLeakReportEmail;
+
+    @Inject
+    public Dependency() {
+    }
+
     @Override
     public void start() {
         // TODO: Think about ways to push these creation rules out of Dependency to cut down
         // on imports.
-        mProviders.put(TIME_TICK_HANDLER, () -> {
-            HandlerThread thread = new HandlerThread("TimeTick");
-            thread.start();
-            return new Handler(thread.getLooper());
-        });
-        mProviders.put(BG_LOOPER, () -> {
-            HandlerThread thread = new HandlerThread("SysUiBg",
-                    Process.THREAD_PRIORITY_BACKGROUND);
-            thread.start();
-            return thread.getLooper();
-        });
-        mProviders.put(BG_HANDLER, () -> new Handler(getDependency(BG_LOOPER)));
-        mProviders.put(MAIN_HANDLER, () -> new Handler(Looper.getMainLooper()));
-        mProviders.put(ActivityStarter.class, () -> new ActivityStarterDelegate());
-        mProviders.put(ActivityStarterDelegate.class, () ->
-                getDependency(ActivityStarter.class));
+        mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get);
+        mProviders.put(BG_LOOPER, mBgLooper::get);
+        mProviders.put(BG_HANDLER, mBgHandler::get);
+        mProviders.put(MAIN_HANDLER, mMainHandler::get);
+        mProviders.put(ActivityStarter.class, mActivityStarter::get);
+        mProviders.put(ActivityStarterDelegate.class, mActivityStarterDelegate::get);
 
-        mProviders.put(AsyncSensorManager.class, () ->
-                new AsyncSensorManager(mContext.getSystemService(SensorManager.class),
-                        getDependency(PluginManager.class)));
+        mProviders.put(AsyncSensorManager.class, mAsyncSensorManager::get);
 
-        mProviders.put(SensorPrivacyManager.class, () ->
-                mContext.getSystemService(SensorPrivacyManager.class));
+        mProviders.put(BluetoothController.class, mBluetoothController::get);
+        mProviders.put(SensorPrivacyManager.class, mSensorPrivacyManager::get);
 
-        mProviders.put(BluetoothController.class, () ->
-                new BluetoothControllerImpl(mContext, getDependency(BG_LOOPER)));
+        mProviders.put(LocationController.class, mLocationController::get);
 
-        mProviders.put(LocationController.class, () ->
-                new LocationControllerImpl(mContext, getDependency(BG_LOOPER)));
+        mProviders.put(RotationLockController.class, mRotationLockController::get);
 
-        mProviders.put(RotationLockController.class, () ->
-                new RotationLockControllerImpl(mContext));
+        mProviders.put(NetworkController.class, mNetworkController::get);
 
-        mProviders.put(NetworkController.class, () ->
-                new NetworkControllerImpl(mContext, getDependency(BG_LOOPER),
-                        getDependency(DeviceProvisionedController.class)));
+        mProviders.put(ZenModeController.class, mZenModeController::get);
 
-        mProviders.put(ZenModeController.class, () ->
-                new ZenModeControllerImpl(mContext, getDependency(MAIN_HANDLER)));
+        mProviders.put(HotspotController.class, mHotspotController::get);
 
-        mProviders.put(HotspotController.class, () ->
-                new HotspotControllerImpl(mContext));
+        mProviders.put(CastController.class, mCastController::get);
 
-        mProviders.put(CastController.class, () ->
-                new CastControllerImpl(mContext));
+        mProviders.put(FlashlightController.class, mFlashlightController::get);
 
-        mProviders.put(FlashlightController.class, () ->
-                new FlashlightControllerImpl(mContext));
+        mProviders.put(KeyguardMonitor.class, mKeyguardMonitor::get);
 
-        mProviders.put(KeyguardMonitor.class, () ->
-                new KeyguardMonitorImpl(mContext));
+        mProviders.put(UserSwitcherController.class, mUserSwitcherController::get);
 
-        mProviders.put(UserSwitcherController.class, () ->
-                new UserSwitcherController(mContext, getDependency(KeyguardMonitor.class),
-                        getDependency(MAIN_HANDLER), getDependency(ActivityStarter.class)));
+        mProviders.put(UserInfoController.class, mUserInfoController::get);
 
-        mProviders.put(UserInfoController.class, () ->
-                new UserInfoControllerImpl(mContext));
+        mProviders.put(BatteryController.class, mBatteryController::get);
 
-        mProviders.put(BatteryController.class, () ->
-                new BatteryControllerImpl(mContext));
+        mProviders.put(ColorDisplayController.class, mColorDisplayController::get);
 
-        mProviders.put(ColorDisplayController.class, () ->
-                new ColorDisplayController(mContext));
+        mProviders.put(ManagedProfileController.class, mManagedProfileController::get);
 
-        mProviders.put(ManagedProfileController.class, () ->
-                new ManagedProfileControllerImpl(mContext));
+        mProviders.put(NextAlarmController.class, mNextAlarmController::get);
 
-        mProviders.put(NextAlarmController.class, () ->
-                new NextAlarmControllerImpl(mContext));
+        mProviders.put(DataSaverController.class, mDataSaverController::get);
 
-        mProviders.put(DataSaverController.class, () ->
-                get(NetworkController.class).getDataSaverController());
+        mProviders.put(AccessibilityController.class, mAccessibilityController::get);
 
-        mProviders.put(AccessibilityController.class, () ->
-                new AccessibilityController(mContext));
+        mProviders.put(DeviceProvisionedController.class, mDeviceProvisionedController::get);
 
-        mProviders.put(DeviceProvisionedController.class, () ->
-                new DeviceProvisionedControllerImpl(mContext));
+        mProviders.put(PluginManager.class, mPluginManager::get);
 
-        mProviders.put(PluginManager.class, () ->
-                new PluginManagerImpl(mContext, new PluginInitializerImpl()));
+        mProviders.put(AssistManager.class, mAssistManager::get);
 
-        mProviders.put(AssistManager.class, () ->
-                new AssistManager(getDependency(DeviceProvisionedController.class), mContext));
+        mProviders.put(SecurityController.class, mSecurityController::get);
 
-        mProviders.put(SecurityController.class, () ->
-                new SecurityControllerImpl(mContext));
+        mProviders.put(LeakDetector.class, mLeakDetector::get);
 
-        mProviders.put(LeakDetector.class, LeakDetector::create);
+        mProviders.put(LEAK_REPORT_EMAIL, mLeakReportEmail::get);
 
-        mProviders.put(LEAK_REPORT_EMAIL, () -> null);
+        mProviders.put(LeakReporter.class, mLeakReporter::get);
 
-        mProviders.put(LeakReporter.class, () -> new LeakReporter(
-                mContext,
-                getDependency(LeakDetector.class),
-                getDependency(LEAK_REPORT_EMAIL)));
+        mProviders.put(GarbageMonitor.class, mGarbageMonitor::get);
 
-        mProviders.put(
-                GarbageMonitor.class,
-                () ->
-                        new GarbageMonitor(
-                                mContext,
-                                getDependency(BG_LOOPER),
-                                getDependency(LeakDetector.class),
-                                getDependency(LeakReporter.class)));
+        mProviders.put(TunerService.class, mTunerService::get);
 
-        mProviders.put(TunerService.class, () ->
-                new TunerServiceImpl(mContext));
+        mProviders.put(StatusBarWindowController.class, mStatusBarWindowController::get);
 
-        mProviders.put(StatusBarWindowController.class, () ->
-                new StatusBarWindowController(mContext));
+        mProviders.put(DarkIconDispatcher.class, mDarkIconDispatcher::get);
 
-        mProviders.put(DarkIconDispatcher.class, () ->
-                new DarkIconDispatcherImpl(mContext));
+        mProviders.put(ConfigurationController.class, mConfigurationController::get);
 
-        mProviders.put(ConfigurationController.class, () ->
-                new ConfigurationControllerImpl(mContext));
+        mProviders.put(StatusBarIconController.class, mStatusBarIconController::get);
 
-        mProviders.put(StatusBarIconController.class, () ->
-                new StatusBarIconControllerImpl(mContext));
+        mProviders.put(ScreenLifecycle.class, mScreenLifecycle::get);
 
-        mProviders.put(ScreenLifecycle.class, () ->
-                new ScreenLifecycle());
+        mProviders.put(WakefulnessLifecycle.class, mWakefulnessLifecycle::get);
 
-        mProviders.put(WakefulnessLifecycle.class, () ->
-                new WakefulnessLifecycle());
+        mProviders.put(FragmentService.class, mFragmentService::get);
 
-        mProviders.put(FragmentService.class, () ->
-                new FragmentService());
+        mProviders.put(ExtensionController.class, mExtensionController::get);
 
-        mProviders.put(ExtensionController.class, () ->
-                new ExtensionControllerImpl(mContext));
+        mProviders.put(PluginDependencyProvider.class, mPluginDependencyProvider::get);
 
-        mProviders.put(PluginDependencyProvider.class, () ->
-                new PluginDependencyProvider(get(PluginManager.class)));
+        mProviders.put(LocalBluetoothManager.class, mLocalBluetoothManager::get);
 
-        mProviders.put(LocalBluetoothManager.class, () ->
-                LocalBluetoothManager.create(mContext, getDependency(BG_HANDLER),
-                        UserHandle.ALL));
+        mProviders.put(VolumeDialogController.class, mVolumeDialogController::get);
 
-        mProviders.put(VolumeDialogController.class, () ->
-                new VolumeDialogControllerImpl(mContext));
+        mProviders.put(MetricsLogger.class, mMetricsLogger::get);
 
-        mProviders.put(MetricsLogger.class, () -> new MetricsLogger());
+        mProviders.put(AccessibilityManagerWrapper.class, mAccessibilityManagerWrapper::get);
 
-        mProviders.put(AccessibilityManagerWrapper.class,
-                () -> new AccessibilityManagerWrapper(mContext));
+        mProviders.put(SysuiColorExtractor.class, mSysuiColorExtractor::get);
 
-        // Creating a new instance will trigger color extraction.
-        // Thankfully this only happens once - during boot - and WallpaperManagerService
-        // loads colors from cache.
-        mProviders.put(SysuiColorExtractor.class, () -> new SysuiColorExtractor(mContext));
+        mProviders.put(TunablePaddingService.class, mTunablePaddingService::get);
 
-        mProviders.put(TunablePaddingService.class, () -> new TunablePaddingService());
+        mProviders.put(ForegroundServiceController.class, mForegroundServiceController::get);
 
-        mProviders.put(ForegroundServiceController.class,
-                () -> new ForegroundServiceControllerImpl(mContext));
+        mProviders.put(UiOffloadThread.class, mUiOffloadThread::get);
 
-        mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
+        mProviders.put(PowerUI.WarningsUI.class, mWarningsUI::get);
 
-        mProviders.put(PowerUI.WarningsUI.class, () -> new PowerNotificationWarnings(mContext));
+        mProviders.put(IconLogger.class, mIconLogger::get);
 
-        mProviders.put(IconLogger.class, () -> new IconLoggerImpl(mContext,
-                getDependency(BG_LOOPER), getDependency(MetricsLogger.class)));
+        mProviders.put(LightBarController.class, mLightBarController::get);
 
-        mProviders.put(LightBarController.class, () -> new LightBarController(mContext));
+        mProviders.put(IWindowManager.class, mIWindowManager::get);
 
-        mProviders.put(IWindowManager.class, () -> WindowManagerGlobal.getWindowManagerService());
+        mProviders.put(OverviewProxyService.class, mOverviewProxyService::get);
 
-        mProviders.put(OverviewProxyService.class, () -> new OverviewProxyService(mContext));
+        mProviders.put(EnhancedEstimates.class, mEnhancedEstimates::get);
 
-        mProviders.put(EnhancedEstimates.class, () -> new EnhancedEstimatesImpl());
+        mProviders.put(VibratorHelper.class, mVibratorHelper::get);
 
-        mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext));
+        mProviders.put(IStatusBarService.class, mIStatusBarService::get);
 
-        mProviders.put(IStatusBarService.class, () -> IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE)));
+        mProviders.put(DisplayMetrics.class, mDisplayMetrics::get);
 
-        // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
-        // anywhere it is needed.
-        mProviders.put(DisplayMetrics.class, () -> new DisplayMetrics());
+        mProviders.put(LockscreenGestureLogger.class, mLockscreenGestureLogger::get);
 
-        mProviders.put(LockscreenGestureLogger.class, () -> new LockscreenGestureLogger());
-
-        mProviders.put(KeyguardEnvironment.class, () -> new KeyguardEnvironmentImpl());
-        mProviders.put(ShadeController.class, () ->
-                SysUiServiceProvider.getComponent(mContext, StatusBar.class));
+        mProviders.put(KeyguardEnvironment.class, mKeyguardEnvironment::get);
+        mProviders.put(ShadeController.class, mShadeController::get);
         mProviders.put(NotificationRemoteInputManager.Callback.class,
-                () -> new StatusBarRemoteInputCallback(mContext));
+                mNotificationRemoteInputManagerCallback::get);
 
-        mProviders.put(InitController.class, InitController::new);
+        mProviders.put(InitController.class, mInitController::get);
 
-        mProviders.put(AppOpsController.class, () ->
-                new AppOpsControllerImpl(mContext, getDependency(BG_LOOPER)));
+        mProviders.put(AppOpsController.class, mAppOpsController::get);
 
-        mProviders.put(DisplayNavigationBarController.class, () ->
-                new DisplayNavigationBarController(mContext, getDependency(MAIN_HANDLER)));
+        mProviders.put(DisplayNavigationBarController.class,
+                mDisplayNavigationBarController::get);
 
-        // Put all dependencies above here so the factory can override them if it wants.
-        SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
+        mProviders.put(StatusBarStateController.class, mStatusBarStateController::get);
+        mProviders.put(NotificationLockscreenUserManager.class,
+                mNotificationLockscreenUserManager::get);
+        mProviders.put(VisualStabilityManager.class, mVisualStabilityManager::get);
+        mProviders.put(NotificationGroupManager.class, mNotificationGroupManager::get);
+        mProviders.put(NotificationGroupAlertTransferHelper.class,
+                mNotificationGroupAlertTransferHelper::get);
+        mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get);
+        mProviders.put(NotificationGutsManager.class, mNotificationGutsManager::get);
+        mProviders.put(AmbientPulseManager.class, mAmbientPulseManager::get);
+        mProviders.put(NotificationBlockingHelperManager.class,
+                mNotificationBlockingHelperManager::get);
+        mProviders.put(NotificationRemoteInputManager.class,
+                mNotificationRemoteInputManager::get);
+        mProviders.put(SmartReplyConstants.class, mSmartReplyConstants::get);
+        mProviders.put(NotificationListener.class, mNotificationListener::get);
+        mProviders.put(NotificationLogger.class, mNotificationLogger::get);
+        mProviders.put(NotificationViewHierarchyManager.class,
+                mNotificationViewHierarchyManager::get);
+        mProviders.put(KeyguardDismissUtil.class, mKeyguardDismissUtil::get);
+        mProviders.put(SmartReplyController.class, mSmartReplyController::get);
+        mProviders.put(RemoteInputQuickSettingsDisabler.class,
+                mRemoteInputQuickSettingsDisabler::get);
+        mProviders.put(BubbleController.class, mBubbleController::get);
+        mProviders.put(NotificationEntryManager.class, mNotificationEntryManager::get);
 
         sDependency = this;
     }
@@ -484,4 +540,20 @@
             return mDisplayName;
         }
     }
+
+    @Subcomponent
+    public interface DependencyInjector {
+        void createSystemUI(Dependency dependency);
+    }
+
+    public static class DependencyCreator implements Injector {
+        @Override
+        public SystemUI apply(Context context) {
+            Dependency dependency = new Dependency();
+            SystemUIFactory.getInstance().getRootComponent()
+                    .createDependency()
+                    .createSystemUI(dependency);
+            return dependency;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
new file mode 100644
index 0000000..e828b23
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import static com.android.systemui.Dependency.BG_HANDLER_NAME;
+import static com.android.systemui.Dependency.BG_LOOPER_NAME;
+import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.SensorManager;
+import android.hardware.SensorPrivacyManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+
+import com.android.internal.app.ColorDisplayController;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.appops.AppOpsControllerImpl;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.PluginDependencyProvider;
+import com.android.systemui.plugins.PluginInitializerImpl;
+import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.power.PowerNotificationWarnings;
+import com.android.systemui.power.PowerUI;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManagerImpl;
+import com.android.systemui.statusbar.DisplayNavigationBarController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryControllerImpl;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.statusbar.policy.ExtensionController;
+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.HotspotController;
+import com.android.systemui.statusbar.policy.HotspotControllerImpl;
+import com.android.systemui.statusbar.policy.IconLogger;
+import com.android.systemui.statusbar.policy.IconLoggerImpl;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.LocationControllerImpl;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.SecurityControllerImpl;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
+import com.android.systemui.tuner.TunablePadding;
+import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerServiceImpl;
+import com.android.systemui.util.AsyncSensorManager;
+import com.android.systemui.util.leak.GarbageMonitor;
+import com.android.systemui.util.leak.LeakDetector;
+import com.android.systemui.util.leak.LeakReporter;
+import com.android.systemui.volume.VolumeDialogControllerImpl;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Provides dependencies for the root component of sysui injection.
+ * See SystemUI/docs/dagger.md
+ */
+@Module
+public class DependencyProvider {
+
+    @Singleton
+    @Provides
+    @Named(TIME_TICK_HANDLER_NAME)
+    public Handler provideHandler() {
+        HandlerThread thread = new HandlerThread("TimeTick");
+        thread.start();
+        return new Handler(thread.getLooper());
+    }
+
+    @Singleton
+    @Provides
+    @Named(BG_LOOPER_NAME)
+    public Looper provideBgLooper() {
+        HandlerThread thread = new HandlerThread("SysUiBg",
+                Process.THREAD_PRIORITY_BACKGROUND);
+        thread.start();
+        return thread.getLooper();
+    }
+
+    @Singleton
+    @Provides
+    @Named(BG_HANDLER_NAME)
+    public Handler provideBgHandler(@Named(BG_LOOPER_NAME) Looper bgLooper) {
+        return new Handler(bgLooper);
+    }
+
+    @Singleton
+    @Provides
+    @Named(MAIN_HANDLER_NAME)
+    public Handler provideMainHandler() {
+        return new Handler(Looper.getMainLooper());
+    }
+
+    @Singleton
+    @Provides
+    public ActivityStarter provideActivityStarter() {
+        return new ActivityStarterDelegate();
+    }
+
+    @Singleton
+    @Provides
+    public InitController provideInitController() {
+        return new InitController();
+    }
+
+    @Singleton
+    @Provides
+    public ActivityStarterDelegate provideActivityStarterDelegate(ActivityStarter starter) {
+        return (ActivityStarterDelegate) starter;
+    }
+
+    @Singleton
+    @Provides
+    public AsyncSensorManager provideAsyncSensorManager(Context context, PluginManager manager) {
+        return new AsyncSensorManager(context.getSystemService(SensorManager.class),
+                manager);
+
+    }
+
+    @Singleton
+    @Provides
+    public BluetoothController provideBluetoothController(Context context,
+            @Named(BG_LOOPER_NAME) Looper looper) {
+        return new BluetoothControllerImpl(context, looper);
+
+    }
+
+    @Singleton
+    @Provides
+    public LocationController provideLocationController(Context context,
+            @Named(BG_LOOPER_NAME) Looper bgLooper) {
+        return new LocationControllerImpl(context, bgLooper);
+
+    }
+
+    @Singleton
+    @Provides
+    public RotationLockController provideRotationLockController(Context context) {
+        return new RotationLockControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public NetworkController provideNetworkController(Context context,
+            @Named(BG_LOOPER_NAME) Looper bgLooper, DeviceProvisionedController controller) {
+        return new NetworkControllerImpl(context, bgLooper,
+                controller);
+
+    }
+
+    @Singleton
+    @Provides
+    public ZenModeController provideZenModeController(Context context,
+            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+        return new ZenModeControllerImpl(context, mainHandler);
+
+    }
+
+    @Singleton
+    @Provides
+    public HotspotController provideHotspotController(Context context) {
+        return new HotspotControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public CastController provideCastController(Context context) {
+        return new CastControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public FlashlightController provideFlashlightController(Context context) {
+        return new FlashlightControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public KeyguardMonitor provideKeyguardMonitor(Context context) {
+        return new KeyguardMonitorImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public UserSwitcherController provideUserSwitcherController(Context context,
+            KeyguardMonitor keyguardMonitor, @Named(MAIN_HANDLER_NAME) Handler mainHandler,
+            ActivityStarter activityStarter) {
+        return new UserSwitcherController(context, keyguardMonitor, mainHandler, activityStarter);
+    }
+
+    @Singleton
+    @Provides
+    public UserInfoController provideUserInfoContrller(Context context) {
+        return new UserInfoControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public BatteryController provideBatteryController(Context context) {
+        return new BatteryControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public ColorDisplayController provideColorDisplayController(Context context) {
+        return new ColorDisplayController(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public ManagedProfileController provideManagedProfileController(Context context) {
+        return new ManagedProfileControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public NextAlarmController provideNextAlarmController(Context context) {
+        return new NextAlarmControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public DataSaverController provideDataSaverController(NetworkController networkController) {
+        return networkController.getDataSaverController();
+    }
+
+    @Singleton
+    @Provides
+    public AccessibilityController provideAccessibilityController(Context context) {
+        return new AccessibilityController(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public DeviceProvisionedController provideDeviceProvisionedController(Context context) {
+        return new DeviceProvisionedControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public PluginManager providePluginManager(Context context) {
+        return new PluginManagerImpl(context, new PluginInitializerImpl());
+
+    }
+
+    @Singleton
+    @Provides
+    public SecurityController provideSecurityController(Context context) {
+        return new SecurityControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public LeakDetector provideLeakDetector() {
+        return LeakDetector.create();
+
+    }
+
+    @Singleton
+    @Provides
+    public LeakReporter provideLeakReporter(Context context, LeakDetector detector,
+            @Nullable @Named(LEAK_REPORT_EMAIL_NAME) String email) {
+        return new LeakReporter(context, detector, email);
+    }
+
+    @Singleton
+    @Provides
+    public GarbageMonitor provideGarbageMonitor(Context context,
+            @Named(BG_LOOPER_NAME) Looper bgLooper, LeakDetector detector, LeakReporter reporter) {
+        return new GarbageMonitor(context, bgLooper, detector, reporter);
+    }
+
+    @Singleton
+    @Provides
+    public TunerService provideTunerService(Context context) {
+        return new TunerServiceImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public StatusBarWindowController provideStatusBarWindowController(Context context) {
+        return new StatusBarWindowController(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public DarkIconDispatcher provideDarkIconDispatcher(Context context) {
+        return new DarkIconDispatcherImpl(context);
+    }
+
+    @Singleton
+    @Provides
+    public ConfigurationController provideConfigurationController(Context context) {
+        return new ConfigurationControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public StatusBarIconController provideStatusBarIconController(Context context) {
+        return new StatusBarIconControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public ScreenLifecycle provideScreenLifecycle() {
+        return new ScreenLifecycle();
+    }
+
+    @Singleton
+    @Provides
+    public WakefulnessLifecycle provideWakefulnessLifecycle() {
+        return new WakefulnessLifecycle();
+    }
+
+    @Singleton
+    @Provides
+    public FragmentService provideFragmentService() {
+        return new FragmentService();
+    }
+
+    @Singleton
+    @Provides
+    public ExtensionController provideExtensionController(Context context) {
+        return new ExtensionControllerImpl(context);
+    }
+
+    @Singleton
+    @Provides
+    public PluginDependencyProvider providePluginDependency(PluginManager pluginManager) {
+        return new PluginDependencyProvider(pluginManager);
+    }
+
+    @Singleton
+    @Provides
+    public LocalBluetoothManager provideLocalBluetoothController(Context context,
+            @Named(BG_HANDLER_NAME) Handler bgHandler) {
+        return LocalBluetoothManager.create(context, bgHandler,
+                UserHandle.ALL);
+    }
+
+    @Singleton
+    @Provides
+    public VolumeDialogController provideVolumeDialogController(Context context) {
+        return new VolumeDialogControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public MetricsLogger provideMetricsLogger() {
+        return new MetricsLogger();
+
+    }
+
+    @Singleton
+    @Provides
+    public AccessibilityManagerWrapper provideAccessibilityManagerWrapper(Context context) {
+        return new AccessibilityManagerWrapper(context);
+
+    }
+
+    @Singleton
+    @Provides
+    // Creating a new instance will trigger color extraction.
+    // Thankfully this only happens once - during boot - and WallpaperManagerService
+    // loads colors from cache.
+    public SysuiColorExtractor provideSysuiColorExtractor(Context context) {
+        return new SysuiColorExtractor(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public TunablePadding.TunablePaddingService provideTunablePaddingService() {
+        return new TunablePaddingService();
+
+    }
+
+    @Singleton
+    @Provides
+    public ForegroundServiceController provideForegroundService(Context context) {
+        return new ForegroundServiceControllerImpl(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public UiOffloadThread provideUiOffloadThread() {
+        Log.d("TestTest", "provideUiOffloadThread");
+        return new UiOffloadThread();
+    }
+
+    @Singleton
+    @Provides
+    public PowerUI.WarningsUI provideWarningsUi(Context context) {
+        return new PowerNotificationWarnings(context);
+    }
+
+    @Singleton
+    @Provides
+    public IconLogger provideIconLogger(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
+            MetricsLogger logger) {
+        return new IconLoggerImpl(context, bgLooper, logger);
+    }
+
+    @Singleton
+    @Provides
+    public LightBarController provideLightBarController(Context context) {
+        return new LightBarController(context);
+    }
+
+    @Singleton
+    @Provides
+    public IWindowManager provideIWindowManager() {
+        return WindowManagerGlobal.getWindowManagerService();
+    }
+
+    @Singleton
+    @Provides
+    public OverviewProxyService provideOverviewProxyService(Context context) {
+        return new OverviewProxyService(context);
+    }
+
+    @Singleton
+    @Provides
+    public VibratorHelper provideVibratorHelper(Context context) {
+        return new VibratorHelper(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public IStatusBarService provideIStatusBarService() {
+        return IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+    }
+
+    @Singleton
+    @Provides
+    // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
+// anywhere it is needed.
+    public DisplayMetrics provideDisplayMetrics() {
+        return new DisplayMetrics();
+
+    }
+
+    @Singleton
+    @Provides
+    public LockscreenGestureLogger provideLockscreenGestureLogger() {
+        return new LockscreenGestureLogger();
+    }
+
+    @Singleton
+    @Provides
+    public ShadeController provideShadeController(Context context) {
+        return SysUiServiceProvider.getComponent(context, StatusBar.class);
+    }
+
+    @Singleton
+    @Provides
+    public NotificationRemoteInputManager.Callback provideNotificationRemoteInputManager(
+            Context context) {
+        return new StatusBarRemoteInputCallback(context);
+
+    }
+
+    @Singleton
+    @Provides
+    public AppOpsController provideAppOpsController(Context context,
+            @Named(BG_LOOPER_NAME) Looper bgLooper) {
+        return new AppOpsControllerImpl(context, bgLooper);
+
+    }
+
+    @Singleton
+    @Provides
+    public DisplayNavigationBarController provideDisplayNavigationBarController(Context context,
+            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+        return new DisplayNavigationBarController(context, mainHandler);
+    }
+
+    @Singleton
+    @Provides
+    public SensorPrivacyManager provideSensorPrivacyManager(Context context) {
+        return context.getSystemService(SensorPrivacyManager.class);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 30fbef6..78a1246 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -24,6 +24,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Map;
+import java.util.function.Function;
 
 public abstract class SystemUI implements SysUiServiceProvider {
     public Context mContext;
@@ -61,4 +62,7 @@
 
         n.addExtras(extras);
     }
+
+    public interface Injector extends Function<Context, SystemUI> {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 92aa652..1d8a21d 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -170,7 +170,11 @@
             Class cls;
             try {
                 cls = Class.forName(clsName);
-                mServices[i] = (SystemUI) cls.newInstance();
+                Object o = cls.newInstance();
+                if (o instanceof SystemUI.Injector) {
+                    o = ((SystemUI.Injector) o).apply(this);
+                }
+                mServices[i] = (SystemUI) o;
             } catch(ClassNotFoundException ex){
                 throw new RuntimeException(ex);
             } catch (IllegalAccessException ex) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 867c917..9bc91ee 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -16,9 +16,11 @@
 
 package com.android.systemui;
 
+import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
+
+import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.content.Context;
-import android.util.ArrayMap;
 import android.util.Log;
 import android.view.ViewGroup;
 
@@ -26,56 +28,54 @@
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.Dependency.DependencyProvider;
-import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.assist.AssistManager;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.qs.QSTileHost;
-import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.SmartReplyController;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
-import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
+import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
-import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.ScrimState;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.policy.SmartReplyConstants;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.volume.VolumeDialogComponent;
 
 import java.util.function.Consumer;
 
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+
 /**
  * Class factory to provide customizable SystemUI components.
  */
+@Module
 public class SystemUIFactory {
     private static final String TAG = "SystemUIFactory";
 
     static SystemUIFactory mFactory;
+    private SystemUIRootComponent mRootComponent;
 
-    public static SystemUIFactory getInstance() {
-        return mFactory;
+    public static <T extends SystemUIFactory> T getInstance() {
+        return (T) mFactory;
     }
 
     public static void createFromConfig(Context context) {
@@ -88,6 +88,7 @@
             Class<?> cls = null;
             cls = context.getClassLoader().loadClass(clsName);
             mFactory = (SystemUIFactory) cls.newInstance();
+            mFactory.init(context);
         } catch (Throwable t) {
             Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
             throw new RuntimeException(t);
@@ -96,6 +97,18 @@
 
     public SystemUIFactory() {}
 
+    protected void init(Context context) {
+        mRootComponent = DaggerSystemUIFactory_SystemUIRootComponent.builder()
+                .systemUIFactory(this)
+                .dependencyProvider(new com.android.systemui.DependencyProvider())
+                .contextHolder(new ContextHolder(context))
+                .build();
+    }
+
+    public SystemUIRootComponent getRootComponent() {
+        return mRootComponent;
+    }
+
     public StatusBarKeyguardViewManager createStatusBarKeyguardViewManager(Context context,
             ViewMediatorCallback viewMediatorCallback, LockPatternUtils lockPatternUtils) {
         return new StatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils);
@@ -137,33 +150,70 @@
         return new VolumeDialogComponent(systemUi, context);
     }
 
-    public void injectDependencies(ArrayMap<Object, DependencyProvider> providers,
+    @Singleton
+    @Provides
+    public NotificationData.KeyguardEnvironment provideKeyguardEnvironment(Context context) {
+        return new KeyguardEnvironmentImpl();
+    }
+
+    @Singleton
+    @Provides
+    public NotificationLockscreenUserManager provideNotificationLockscreenUserManager(
             Context context) {
-        providers.put(StatusBarStateController.class, StatusBarStateController::new);
-        providers.put(NotificationLockscreenUserManager.class,
-                () -> new NotificationLockscreenUserManagerImpl(context));
-        providers.put(VisualStabilityManager.class, VisualStabilityManager::new);
-        providers.put(NotificationGroupManager.class, NotificationGroupManager::new);
-        providers.put(NotificationGroupAlertTransferHelper.class,
-                NotificationGroupAlertTransferHelper::new);
-        providers.put(NotificationMediaManager.class, () -> new NotificationMediaManager(context));
-        providers.put(NotificationGutsManager.class, () -> new NotificationGutsManager(context));
-        providers.put(AmbientPulseManager.class, () -> new AmbientPulseManager(context));
-        providers.put(NotificationBlockingHelperManager.class,
-                () -> new NotificationBlockingHelperManager(context));
-        providers.put(NotificationRemoteInputManager.class,
-                () -> new NotificationRemoteInputManager(context));
-        providers.put(SmartReplyConstants.class,
-                () -> new SmartReplyConstants(Dependency.get(Dependency.MAIN_HANDLER), context));
-        providers.put(NotificationListener.class, () -> new NotificationListener(context));
-        providers.put(NotificationLogger.class, NotificationLogger::new);
-        providers.put(NotificationViewHierarchyManager.class,
-                () -> new NotificationViewHierarchyManager(context));
-        providers.put(NotificationEntryManager.class, () -> new NotificationEntryManager(context));
-        providers.put(KeyguardDismissUtil.class, KeyguardDismissUtil::new);
-        providers.put(SmartReplyController.class, () -> new SmartReplyController());
-        providers.put(RemoteInputQuickSettingsDisabler.class,
-                () -> new RemoteInputQuickSettingsDisabler(context));
-        providers.put(BubbleController.class, () -> new BubbleController(context));
+        return new NotificationLockscreenUserManagerImpl(context);
+    }
+
+    @Singleton
+    @Provides
+    public AssistManager provideAssistManager(DeviceProvisionedController controller,
+            Context context) {
+        return new AssistManager(controller, context);
+    }
+
+    @Singleton
+    @Provides
+    public NotificationEntryManager provideNotificationEntryManager(Context context) {
+        return new NotificationEntryManager(context);
+    }
+
+    @Singleton
+    @Provides
+    public EnhancedEstimates provideEnhancedEstimates(Context context) {
+        return new EnhancedEstimatesImpl();
+    }
+
+    @Singleton
+    @Provides
+    @Named(LEAK_REPORT_EMAIL_NAME)
+    @Nullable
+    public String provideLeakReportEmail() {
+        return null;
+    }
+
+    @Singleton
+    @Provides
+    public NotificationListener provideNotificationListener(Context context) {
+        return new NotificationListener(context);
+    }
+
+    @Module
+    protected static class ContextHolder {
+        private Context mContext;
+
+        public ContextHolder(Context context) {
+            mContext = context;
+        }
+
+        @Provides
+        public Context provideContext() {
+            return mContext;
+        }
+    }
+
+    @Singleton
+    @Component(modules = {SystemUIFactory.class, DependencyProvider.class, ContextHolder.class})
+    public interface SystemUIRootComponent {
+        @Singleton
+        Dependency.DependencyInjector createDependency();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 1e91ef3..c8595eb 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -42,12 +42,16 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Bubbles are a special type of content that can "float" on top of other apps or System UI.
  * Bubbles can be expanded to show more content.
  *
  * The controller manages addition, removal, and visible state of bubbles on screen.
  */
+@Singleton
 public class BubbleController {
     private static final int MAX_BUBBLES = 5; // TODO: actually enforce this
 
@@ -117,6 +121,7 @@
         void onBubbleExpandChanged(boolean isExpanding, float amount);
     }
 
+    @Inject
     public BubbleController(Context context) {
         mContext = context;
         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java
index 8821679..9bfd4ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java
@@ -28,17 +28,22 @@
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Manager which handles high priority notifications that should "pulse" in when the device is
  * dozing and/or in AOD.  The pulse uses the notification's ambient view and pops in briefly
  * before automatically dismissing the alert.
  */
+@Singleton
 public class AmbientPulseManager extends AlertingNotificationManager {
 
     protected final ArraySet<OnAmbientChangedListener> mListeners = new ArraySet<>();
     @VisibleForTesting
     protected long mExtensionTime;
 
+    @Inject
     public AmbientPulseManager(@NonNull final Context context) {
         Resources resources = context.getResources();
         mAutoDismissNotificationDecay = resources.getInteger(R.integer.ambient_notification_decay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index f045548..7d80860 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -61,10 +61,14 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Handles tasks and state related to media notifications. For example, there is a 'current' media
  * notification, which this class keeps track of.
  */
+@Singleton
 public class NotificationMediaManager implements Dumpable {
     private static final String TAG = "NotificationMediaManager";
     public static final boolean DEBUG_MEDIA = false;
@@ -157,6 +161,7 @@
         return mEntryManager;
     }
 
+    @Inject
     public NotificationMediaManager(Context context) {
         mContext = context;
         mMediaSessionManager
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 9391737..d1556fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -59,12 +59,16 @@
 import java.util.ArrayList;
 import java.util.Set;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Class for handling remote input state over a set of notifications. This class handles things
  * like keeping notifications temporarily that were cancelled as a response to a remote input
  * interaction, keeping track of notifications to remove when NotificationPresenter is collapsed,
  * and handling clicks on remote views.
  */
+@Singleton
 public class NotificationRemoteInputManager implements Dumpable {
     public static final boolean ENABLE_REMOTE_INPUT =
             SystemProperties.getBoolean("debug.enable_remote_input", true);
@@ -229,6 +233,7 @@
         return mShadeController;
     }
 
+    @Inject
     public NotificationRemoteInputManager(Context context) {
         mContext = context;
         mBarService = IStatusBarService.Stub.asInterface(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 0702f1b..2524747 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -41,6 +41,9 @@
 import java.util.List;
 import java.util.Stack;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * NotificationViewHierarchyManager manages updating the view hierarchy of notification views based
  * on their group structure. For example, if a notification becomes bundled with another,
@@ -48,6 +51,7 @@
  * tell NotificationListContainer which notifications to display, and inform it of changes to those
  * notifications that might affect their display.
  */
+@Singleton
 public class NotificationViewHierarchyManager {
     private static final String TAG = "NotificationViewHierarchyManager";
 
@@ -123,6 +127,7 @@
         return mShadeController;
     }
 
+    @Inject
     public NotificationViewHierarchyManager(Context context) {
         Resources res = context.getResources();
         mAlwaysExpandNonGroupedNotification =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index e31f90d5..6f1548d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -27,10 +27,14 @@
 
 import java.util.Set;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Handles when smart replies are added to a notification
  * and clicked upon.
  */
+@Singleton
 public class SmartReplyController {
     private IStatusBarService mBarService;
     private Set<String> mSendingKeys = new ArraySet<>();
@@ -38,7 +42,7 @@
     private final NotificationEntryManager mEntryManager =
             Dependency.get(NotificationEntryManager.class);
 
-
+    @Inject
     public SmartReplyController() {
         mBarService = Dependency.get(IStatusBarService.class);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index 3f84416..087b655 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -35,9 +35,13 @@
 import java.util.ArrayList;
 import java.util.Comparator;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Tracks and reports on {@link StatusBarState}.
  */
+@Singleton
 public class StatusBarStateController implements CallbackController<StateListener> {
     private static final String TAG = "SbStateController";
 
@@ -101,6 +105,10 @@
     public static final int RANK_STACK_SCROLLER = 2;
     public static final int RANK_SHELF = 3;
 
+    @Inject
+    public StatusBarStateController() {
+    }
+
     public int getState() {
         return mState;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index fce7980..abb7b41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -25,10 +25,14 @@
 
 import java.util.ArrayList;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * A manager that ensures that notifications are visually stable. It will suppress reorderings
  * and reorder at the right time when they are out of view.
  */
+@Singleton
 public class VisualStabilityManager implements OnHeadsUpChangedListener {
 
     private final ArrayList<Callback> mCallbacks =  new ArrayList<>();
@@ -42,6 +46,10 @@
     private ArraySet<View> mAddedChildren = new ArraySet<>();
     private boolean mPulsing;
 
+    @Inject
+    public VisualStabilityManager() {
+    }
+
     /**
      * Add a callback to invoke when reordering is allowed again.
      * @param callback
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 9f02e54..eb1fc30 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
@@ -40,10 +40,14 @@
 import java.util.Collection;
 import java.util.Collections;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Handles notification logging, in particular, logging which notifications are visible and which
  * are not.
  */
+@Singleton
 public class NotificationLogger implements StateListener {
     private static final String TAG = "NotificationLogger";
 
@@ -145,6 +149,7 @@
         }
     };
 
+    @Inject
     public NotificationLogger() {
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 16796dd..607d96d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -34,10 +34,14 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Manager for the notification blocking helper - tracks and helps create the blocking helper
  * affordance.
  */
+@Singleton
 public class NotificationBlockingHelperManager {
     /** Enables debug logging and always makes the blocking helper show up after a dismiss. */
     private static final boolean DEBUG = false;
@@ -54,6 +58,7 @@
      */
     private boolean mIsShadeExpanded;
 
+    @Inject
     public NotificationBlockingHelperManager(Context context) {
         mContext = context;
         mNonBlockablePkgs = new HashSet<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 2e45527..ac4e583 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -57,10 +57,14 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Handles various NotificationGuts related tasks, such as binding guts to a row, opening and
  * closing guts, and keeping track of the currently exposed notification guts.
  */
+@Singleton
 public class NotificationGutsManager implements Dumpable, NotificationLifetimeExtender {
     private static final String TAG = "NotificationGutsManager";
 
@@ -91,6 +95,7 @@
     @VisibleForTesting
     protected String mKeyToRemoveOnGutsClosed;
 
+    @Inject
     public NotificationGutsManager(Context context) {
         mContext = context;
         mAccessibilityManager = (AccessibilityManager)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
index b3d0bf8..e541e14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
@@ -20,15 +20,23 @@
 
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Executes actions that require the screen to be unlocked. Delegates the actual handling to an
  * implementation passed via {@link #setDismissHandler}.
  */
+@Singleton
 public class KeyguardDismissUtil implements KeyguardDismissHandler {
     private static final String TAG = "KeyguardDismissUtil";
 
     private volatile KeyguardDismissHandler mDismissHandler;
 
+    @Inject
+    public KeyguardDismissUtil() {
+    }
+
     /** Sets the actual {@link DismissHandler} implementation. */
     public void setDismissHandler(KeyguardDismissHandler dismissHandler) {
         mDismissHandler = dismissHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index dd81c4e..6732bbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -42,11 +42,15 @@
 import java.util.ArrayList;
 import java.util.Objects;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * A helper class dealing with the alert interactions between {@link NotificationGroupManager},
  * {@link HeadsUpManager}, {@link AmbientPulseManager}. In particular, this class deals with keeping
  * the correct notification in a group alerting based off the group suppression.
  */
+@Singleton
 public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedListener,
         OnAmbientChangedListener, StateListener {
 
@@ -73,6 +77,7 @@
 
     private boolean mIsDozing;
 
+    @Inject
     public NotificationGroupAlertTransferHelper() {
         Dependency.get(StatusBarStateController.class).addCallback(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 8f4369a..3c1c076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -39,9 +39,13 @@
 import java.util.Map;
 import java.util.Objects;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * A class to handle notifications and their corresponding groups.
  */
+@Singleton
 public class NotificationGroupManager implements OnHeadsUpChangedListener,
         OnAmbientChangedListener, StateListener {
 
@@ -54,6 +58,7 @@
     private AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
     private boolean mIsUpdatingUnchangedGroup;
 
+    @Inject
     public NotificationGroupManager() {
         Dependency.get(StatusBarStateController.class).addCallback(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
index c2933e1..2a10db6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
@@ -27,9 +27,13 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.StatusBar;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Let {@link RemoteInputView} to control the visibility of QuickSetting.
  */
+@Singleton
 public class RemoteInputQuickSettingsDisabler
         implements ConfigurationController.ConfigurationListener {
 
@@ -39,6 +43,7 @@
     private int mLastOrientation;
     @VisibleForTesting CommandQueue mCommandQueue;
 
+    @Inject
     public RemoteInputQuickSettingsDisabler(Context context) {
         mContext = context;
         mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 71d6e54..6193159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -27,6 +29,11 @@
 
 import com.android.systemui.R;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Singleton
 public final class SmartReplyConstants extends ContentObserver {
 
     private static final String TAG = "SmartReplyConstants";
@@ -47,7 +54,8 @@
     private final Context mContext;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
 
-    public SmartReplyConstants(Handler handler, Context context) {
+    @Inject
+    public SmartReplyConstants(@Named(MAIN_HANDLER_NAME) Handler handler, Context context) {
         super(handler);
 
         mContext = context;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
index 0c8d137..18bf75e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
@@ -29,9 +29,10 @@
             mComponents = ((SysuiTestableContext) context).getComponents();
         }
         mContext = context;
-        if (SystemUIFactory.getInstance() == null) {
-            SystemUIFactory.createFromConfig(context);
-        }
+        SystemUIFactory.createFromConfig(context);
+        SystemUIFactory.getInstance().getRootComponent()
+                .createDependency()
+                .createSystemUI(this);
         start();
     }