blob: 135b12902a2560e9a8697c9dd4858b46f2a66abb [file] [log] [blame]
Jason Monk9c7844c2017-01-18 15:21:53 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui;
16
17import android.content.res.Configuration;
18import android.os.Handler;
19import android.os.HandlerThread;
20import android.os.Looper;
21import android.os.Process;
22import android.util.ArrayMap;
23
24import com.android.internal.annotations.VisibleForTesting;
25import com.android.systemui.assist.AssistManager;
26import com.android.systemui.statusbar.phone.ManagedProfileController;
27import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
28import com.android.systemui.statusbar.policy.AccessibilityController;
29import com.android.systemui.statusbar.policy.BatteryController;
30import com.android.systemui.statusbar.policy.BatteryControllerImpl;
31import com.android.systemui.statusbar.policy.BluetoothController;
32import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
33import com.android.systemui.statusbar.policy.CastController;
34import com.android.systemui.statusbar.policy.CastControllerImpl;
35import com.android.systemui.statusbar.policy.DataSaverController;
36import com.android.systemui.statusbar.policy.DeviceProvisionedController;
37import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
38import com.android.systemui.statusbar.policy.FlashlightController;
39import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
40import com.android.systemui.statusbar.policy.HotspotController;
41import com.android.systemui.statusbar.policy.HotspotControllerImpl;
42import com.android.systemui.statusbar.policy.KeyguardMonitor;
43import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
44import com.android.systemui.statusbar.policy.LocationController;
45import com.android.systemui.statusbar.policy.LocationControllerImpl;
46import com.android.systemui.statusbar.policy.NetworkController;
47import com.android.systemui.statusbar.policy.NetworkControllerImpl;
48import com.android.systemui.statusbar.policy.NextAlarmController;
49import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
50import com.android.systemui.statusbar.policy.RotationLockController;
51import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
52import com.android.systemui.statusbar.policy.SecurityController;
53import com.android.systemui.statusbar.policy.SecurityControllerImpl;
54import com.android.systemui.statusbar.policy.UserInfoController;
55import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
56import com.android.systemui.statusbar.policy.UserSwitcherController;
57import com.android.systemui.statusbar.policy.ZenModeController;
58import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
59
60import java.io.FileDescriptor;
61import java.io.PrintWriter;
62
63/**
64 * Class to handle ugly dependencies throughout sysui until we determine the
65 * long-term dependency injection solution.
66 *
67 * Classes added here should be things that are expected to live the lifetime of sysui,
68 * and are generally applicable to many parts of sysui. They will be lazily
69 * initialized to ensure they aren't created on form factors that don't need them
70 * (e.g. HotspotController on TV). Despite being lazily initialized, it is expected
71 * that all dependencies will be gotten during sysui startup, and not during runtime
72 * to avoid jank.
73 *
74 * All classes used here are expected to manage their own lifecycle, meaning if
75 * they have no clients they should not have any registered resources like bound
76 * services, registered receivers, etc.
77 */
78public class Dependency extends SystemUI {
79
80 /**
81 * Key for getting a background Looper for background work.
82 */
83 public static final String BG_LOOPER = "background_loooper";
84 /**
85 * Key for getting a Handler for receiving time tick broadcasts on.
86 */
87 public static final String TIME_TICK_HANDLER = "time_tick_handler";
88 /**
89 * Generic handler on the main thread.
90 */
91 public static final String MAIN_HANDLER = "main_handler";
92
93 private final ArrayMap<String, Object> mDependencies = new ArrayMap<>();
94 private final ArrayMap<String, DependencyProvider> mProviders = new ArrayMap<>();
95
96 @Override
97 public void start() {
98 sDependency = this;
99 // TODO: Think about ways to push these creation rules out of Dependency to cut down
100 // on imports.
101 mProviders.put(TIME_TICK_HANDLER, () -> {
102 HandlerThread thread = new HandlerThread("TimeTick");
103 thread.start();
104 return new Handler(thread.getLooper());
105 });
106 mProviders.put(BG_LOOPER, () -> {
107 HandlerThread thread = new HandlerThread("SysUiBg",
108 Process.THREAD_PRIORITY_BACKGROUND);
109 thread.start();
110 return thread.getLooper();
111 });
112 mProviders.put(MAIN_HANDLER, () -> new Handler(Looper.getMainLooper()));
113 mProviders.put(ActivityStarter.class.getName(), () -> new ActivityStarterDelegate());
114 mProviders.put(ActivityStarterDelegate.class.getName(), () ->
115 getDependency(ActivityStarter.class));
116
117 mProviders.put(BluetoothController.class.getName(), () ->
118 new BluetoothControllerImpl(mContext, getDependency(BG_LOOPER)));
119
120 mProviders.put(LocationController.class.getName(), () ->
121 new LocationControllerImpl(mContext, getDependency(BG_LOOPER)));
122
123 mProviders.put(RotationLockController.class.getName(), () ->
124 new RotationLockControllerImpl(mContext));
125
126 mProviders.put(NetworkController.class.getName(), () ->
127 new NetworkControllerImpl(mContext, getDependency(BG_LOOPER),
128 getDependency(DeviceProvisionedController.class)));
129
130 mProviders.put(ZenModeController.class.getName(), () ->
131 new ZenModeControllerImpl(mContext, getDependency(MAIN_HANDLER)));
132
133 mProviders.put(HotspotController.class.getName(), () ->
134 new HotspotControllerImpl(mContext));
135
136 mProviders.put(CastController.class.getName(), () ->
137 new CastControllerImpl(mContext));
138
139 mProviders.put(FlashlightController.class.getName(), () ->
140 new FlashlightControllerImpl(mContext));
141
142 mProviders.put(KeyguardMonitor.class.getName(), () ->
143 new KeyguardMonitorImpl(mContext));
144
145 mProviders.put(UserSwitcherController.class.getName(), () ->
146 new UserSwitcherController(mContext, getDependency(KeyguardMonitor.class),
147 getDependency(MAIN_HANDLER), getDependency(ActivityStarter.class)));
148
149 mProviders.put(UserInfoController.class.getName(), () ->
150 new UserInfoControllerImpl(mContext));
151
152 mProviders.put(BatteryController.class.getName(), () ->
153 new BatteryControllerImpl(mContext));
154
155 mProviders.put(ManagedProfileController.class.getName(), () ->
156 new ManagedProfileControllerImpl(mContext));
157
158 mProviders.put(NextAlarmController.class.getName(), () ->
159 new NextAlarmControllerImpl(mContext));
160
161 mProviders.put(DataSaverController.class.getName(), () ->
162 get(NetworkController.class).getDataSaverController());
163
164 mProviders.put(AccessibilityController.class.getName(), () ->
165 new AccessibilityController(mContext));
166
167 mProviders.put(DeviceProvisionedController.class.getName(), () ->
168 new DeviceProvisionedControllerImpl(mContext));
169
170 mProviders.put(AssistManager.class.getName(), () ->
171 new AssistManager(getDependency(DeviceProvisionedController.class), mContext));
172
173 mProviders.put(SecurityController.class.getName(), () ->
174 new SecurityControllerImpl(mContext));
175
176 // Put all dependencies above here so the factory can override them if it wants.
177 SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
178 }
179
180 @Override
181 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
182 super.dump(fd, pw, args);
183 pw.println("Dumping existing controllers:");
184 mDependencies.values().stream().filter(obj -> obj instanceof Dumpable)
185 .forEach(o -> ((Dumpable) o).dump(fd, pw, args));
186 }
187
188 @Override
189 protected void onConfigurationChanged(Configuration newConfig) {
190 super.onConfigurationChanged(newConfig);
191 mDependencies.values().stream().filter(obj -> obj instanceof ConfigurationChangedReceiver)
192 .forEach(o -> ((ConfigurationChangedReceiver) o).onConfigurationChanged(newConfig));
193 }
194
195 protected final <T> T getDependency(Class<T> cls) {
196 return getDependency(cls.getName());
197 }
198
199 protected final <T> T getDependency(String cls) {
200 T obj = (T) mDependencies.get(cls);
201 if (obj == null) {
202 obj = createDependency(cls);
203 mDependencies.put(cls, obj);
204 }
205 return obj;
206 }
207
208 @VisibleForTesting
209 protected <T> T createDependency(String cls) {
210 DependencyProvider<T> provider = mProviders.get(cls);
211 if (provider == null) {
212 throw new IllegalArgumentException("Unsupported dependency " + cls);
213 }
214 return provider.createDependency();
215 }
216
217 private static Dependency sDependency;
218
219 public interface DependencyProvider<T> {
220 T createDependency();
221 }
222
223 public static <T> T get(Class<T> cls) {
224 return sDependency.getDependency(cls.getName());
225 }
226
227 public static <T> T get(String cls) {
228 return sDependency.getDependency(cls);
229 }
230}