1 /*
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 
15 package com.android.systemui;
16 
17 import android.content.Context;
18 import android.content.res.Configuration;
19 import android.hardware.SensorManager;
20 import android.os.Handler;
21 import android.os.HandlerThread;
22 import android.os.Looper;
23 import android.os.Process;
24 import android.os.ServiceManager;
25 import android.util.ArrayMap;
26 import android.view.IWindowManager;
27 import android.view.WindowManagerGlobal;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 import com.android.internal.app.ColorDisplayController;
31 import com.android.internal.logging.MetricsLogger;
32 import com.android.internal.statusbar.IStatusBarService;
33 import com.android.internal.util.Preconditions;
34 import com.android.settingslib.bluetooth.LocalBluetoothManager;
35 import com.android.systemui.assist.AssistManager;
36 import com.android.systemui.colorextraction.SysuiColorExtractor;
37 import com.android.systemui.fragments.FragmentService;
38 import com.android.systemui.keyguard.ScreenLifecycle;
39 import com.android.systemui.keyguard.WakefulnessLifecycle;
40 import com.android.systemui.plugins.ActivityStarter;
41 import com.android.systemui.plugins.PluginDependencyProvider;
42 import com.android.systemui.plugins.PluginManager;
43 import com.android.systemui.plugins.PluginManagerImpl;
44 import com.android.systemui.plugins.VolumeDialogController;
45 import com.android.systemui.power.EnhancedEstimates;
46 import com.android.systemui.power.EnhancedEstimatesImpl;
47 import com.android.systemui.power.PowerNotificationWarnings;
48 import com.android.systemui.power.PowerUI;
49 import com.android.systemui.statusbar.AppOpsListener;
50 import com.android.systemui.statusbar.VibratorHelper;
51 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
52 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
53 import com.android.systemui.statusbar.phone.LightBarController;
54 import com.android.systemui.statusbar.phone.ManagedProfileController;
55 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
56 import com.android.systemui.statusbar.phone.StatusBarIconController;
57 import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
58 import com.android.systemui.statusbar.phone.StatusBarWindowManager;
59 import com.android.systemui.statusbar.policy.AccessibilityController;
60 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
61 import com.android.systemui.statusbar.policy.BatteryController;
62 import com.android.systemui.statusbar.policy.BatteryControllerImpl;
63 import com.android.systemui.statusbar.policy.BluetoothController;
64 import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
65 import com.android.systemui.statusbar.policy.CastController;
66 import com.android.systemui.statusbar.policy.CastControllerImpl;
67 import com.android.systemui.statusbar.policy.ConfigurationController;
68 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
69 import com.android.systemui.statusbar.policy.DataSaverController;
70 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
71 import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
72 import com.android.systemui.statusbar.policy.ExtensionController;
73 import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
74 import com.android.systemui.statusbar.policy.FlashlightController;
75 import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
76 import com.android.systemui.statusbar.policy.HotspotController;
77 import com.android.systemui.statusbar.policy.HotspotControllerImpl;
78 import com.android.systemui.statusbar.policy.IconLogger;
79 import com.android.systemui.statusbar.policy.IconLoggerImpl;
80 import com.android.systemui.statusbar.policy.KeyguardMonitor;
81 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
82 import com.android.systemui.statusbar.policy.LocationController;
83 import com.android.systemui.statusbar.policy.LocationControllerImpl;
84 import com.android.systemui.statusbar.policy.NetworkController;
85 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
86 import com.android.systemui.statusbar.policy.NextAlarmController;
87 import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
88 import com.android.systemui.statusbar.policy.RotationLockController;
89 import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
90 import com.android.systemui.statusbar.policy.SecurityController;
91 import com.android.systemui.statusbar.policy.SecurityControllerImpl;
92 import com.android.systemui.statusbar.policy.UserInfoController;
93 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
94 import com.android.systemui.statusbar.policy.UserSwitcherController;
95 import com.android.systemui.statusbar.policy.ZenModeController;
96 import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
97 import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
98 import com.android.systemui.tuner.TunerService;
99 import com.android.systemui.tuner.TunerServiceImpl;
100 import com.android.systemui.util.AsyncSensorManager;
101 import com.android.systemui.util.leak.GarbageMonitor;
102 import com.android.systemui.util.leak.LeakDetector;
103 import com.android.systemui.util.leak.LeakReporter;
104 import com.android.systemui.volume.VolumeDialogControllerImpl;
105 
106 import java.io.FileDescriptor;
107 import java.io.PrintWriter;
108 import java.util.HashMap;
109 import java.util.function.Consumer;
110 
111 /**
112  * Class to handle ugly dependencies throughout sysui until we determine the
113  * long-term dependency injection solution.
114  *
115  * Classes added here should be things that are expected to live the lifetime of sysui,
116  * and are generally applicable to many parts of sysui. They will be lazily
117  * initialized to ensure they aren't created on form factors that don't need them
118  * (e.g. HotspotController on TV). Despite being lazily initialized, it is expected
119  * that all dependencies will be gotten during sysui startup, and not during runtime
120  * to avoid jank.
121  *
122  * All classes used here are expected to manage their own lifecycle, meaning if
123  * they have no clients they should not have any registered resources like bound
124  * services, registered receivers, etc.
125  */
126 public class Dependency extends SystemUI {
127     private static final String TAG = "Dependency";
128 
129     /**
130      * Key for getting a background Looper for background work.
131      */
132     public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>("background_looper");
133     /**
134      * Key for getting a Handler for receiving time tick broadcasts on.
135      */
136     public static final DependencyKey<Handler> TIME_TICK_HANDLER =
137             new DependencyKey<>("time_tick_handler");
138     /**
139      * Generic handler on the main thread.
140      */
141     public static final DependencyKey<Handler> MAIN_HANDLER = new DependencyKey<>("main_handler");
142 
143     /**
144      * An email address to send memory leak reports to by default.
145      */
146     public static final DependencyKey<String> LEAK_REPORT_EMAIL
147             = new DependencyKey<>("leak_report_email");
148 
149     private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();
150     private final ArrayMap<Object, DependencyProvider> mProviders = new ArrayMap<>();
151 
152     @Override
start()153     public void start() {
154         // TODO: Think about ways to push these creation rules out of Dependency to cut down
155         // on imports.
156         mProviders.put(TIME_TICK_HANDLER, () -> {
157             HandlerThread thread = new HandlerThread("TimeTick");
158             thread.start();
159             return new Handler(thread.getLooper());
160         });
161         mProviders.put(BG_LOOPER, () -> {
162             HandlerThread thread = new HandlerThread("SysUiBg",
163                     Process.THREAD_PRIORITY_BACKGROUND);
164             thread.start();
165             return thread.getLooper();
166         });
167         mProviders.put(MAIN_HANDLER, () -> new Handler(Looper.getMainLooper()));
168         mProviders.put(ActivityStarter.class, () -> new ActivityStarterDelegate());
169         mProviders.put(ActivityStarterDelegate.class, () ->
170                 getDependency(ActivityStarter.class));
171 
172         mProviders.put(AsyncSensorManager.class, () ->
173                 new AsyncSensorManager(mContext.getSystemService(SensorManager.class)));
174 
175         mProviders.put(BluetoothController.class, () ->
176                 new BluetoothControllerImpl(mContext, getDependency(BG_LOOPER)));
177 
178         mProviders.put(LocationController.class, () ->
179                 new LocationControllerImpl(mContext, getDependency(BG_LOOPER)));
180 
181         mProviders.put(RotationLockController.class, () ->
182                 new RotationLockControllerImpl(mContext));
183 
184         mProviders.put(NetworkController.class, () ->
185                 new NetworkControllerImpl(mContext, getDependency(BG_LOOPER),
186                         getDependency(DeviceProvisionedController.class)));
187 
188         mProviders.put(ZenModeController.class, () ->
189                 new ZenModeControllerImpl(mContext, getDependency(MAIN_HANDLER)));
190 
191         mProviders.put(HotspotController.class, () ->
192                 new HotspotControllerImpl(mContext));
193 
194         mProviders.put(CastController.class, () ->
195                 new CastControllerImpl(mContext));
196 
197         mProviders.put(FlashlightController.class, () ->
198                 new FlashlightControllerImpl(mContext));
199 
200         mProviders.put(KeyguardMonitor.class, () ->
201                 new KeyguardMonitorImpl(mContext));
202 
203         mProviders.put(UserSwitcherController.class, () ->
204                 new UserSwitcherController(mContext, getDependency(KeyguardMonitor.class),
205                         getDependency(MAIN_HANDLER), getDependency(ActivityStarter.class)));
206 
207         mProviders.put(UserInfoController.class, () ->
208                 new UserInfoControllerImpl(mContext));
209 
210         mProviders.put(BatteryController.class, () ->
211                 new BatteryControllerImpl(mContext));
212 
213         mProviders.put(ColorDisplayController.class, () ->
214                 new ColorDisplayController(mContext));
215 
216         mProviders.put(ManagedProfileController.class, () ->
217                 new ManagedProfileControllerImpl(mContext));
218 
219         mProviders.put(NextAlarmController.class, () ->
220                 new NextAlarmControllerImpl(mContext));
221 
222         mProviders.put(DataSaverController.class, () ->
223                 get(NetworkController.class).getDataSaverController());
224 
225         mProviders.put(AccessibilityController.class, () ->
226                 new AccessibilityController(mContext));
227 
228         mProviders.put(DeviceProvisionedController.class, () ->
229                 new DeviceProvisionedControllerImpl(mContext));
230 
231         mProviders.put(PluginManager.class, () ->
232                 new PluginManagerImpl(mContext));
233 
234         mProviders.put(AssistManager.class, () ->
235                 new AssistManager(getDependency(DeviceProvisionedController.class), mContext));
236 
237         mProviders.put(SecurityController.class, () ->
238                 new SecurityControllerImpl(mContext));
239 
240         mProviders.put(LeakDetector.class, LeakDetector::create);
241 
242         mProviders.put(LEAK_REPORT_EMAIL, () -> null);
243 
244         mProviders.put(LeakReporter.class, () -> new LeakReporter(
245                 mContext,
246                 getDependency(LeakDetector.class),
247                 getDependency(LEAK_REPORT_EMAIL)));
248 
249         mProviders.put(
250                 GarbageMonitor.class,
251                 () ->
252                         new GarbageMonitor(
253                                 mContext,
254                                 getDependency(BG_LOOPER),
255                                 getDependency(LeakDetector.class),
256                                 getDependency(LeakReporter.class)));
257 
258         mProviders.put(TunerService.class, () ->
259                 new TunerServiceImpl(mContext));
260 
261         mProviders.put(StatusBarWindowManager.class, () ->
262                 new StatusBarWindowManager(mContext));
263 
264         mProviders.put(DarkIconDispatcher.class, () ->
265                 new DarkIconDispatcherImpl(mContext));
266 
267         mProviders.put(ConfigurationController.class, () ->
268                 new ConfigurationControllerImpl(mContext));
269 
270         mProviders.put(StatusBarIconController.class, () ->
271                 new StatusBarIconControllerImpl(mContext));
272 
273         mProviders.put(ScreenLifecycle.class, () ->
274                 new ScreenLifecycle());
275 
276         mProviders.put(WakefulnessLifecycle.class, () ->
277                 new WakefulnessLifecycle());
278 
279         mProviders.put(FragmentService.class, () ->
280                 new FragmentService(mContext));
281 
282         mProviders.put(ExtensionController.class, () ->
283                 new ExtensionControllerImpl(mContext));
284 
285         mProviders.put(PluginDependencyProvider.class, () ->
286                 new PluginDependencyProvider(get(PluginManager.class)));
287 
288         mProviders.put(LocalBluetoothManager.class, () ->
289                 LocalBluetoothManager.getInstance(mContext, null));
290 
291         mProviders.put(VolumeDialogController.class, () ->
292                 new VolumeDialogControllerImpl(mContext));
293 
294         mProviders.put(MetricsLogger.class, () -> new MetricsLogger());
295 
296         mProviders.put(AccessibilityManagerWrapper.class,
297                 () -> new AccessibilityManagerWrapper(mContext));
298 
299         // Creating a new instance will trigger color extraction.
300         // Thankfully this only happens once - during boot - and WallpaperManagerService
301         // loads colors from cache.
302         mProviders.put(SysuiColorExtractor.class, () -> new SysuiColorExtractor(mContext));
303 
304         mProviders.put(TunablePaddingService.class, () -> new TunablePaddingService());
305 
306         mProviders.put(ForegroundServiceController.class,
307                 () -> new ForegroundServiceControllerImpl(mContext));
308 
309         mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
310 
311         mProviders.put(PowerUI.WarningsUI.class, () -> new PowerNotificationWarnings(mContext));
312 
313         mProviders.put(IconLogger.class, () -> new IconLoggerImpl(mContext,
314                 getDependency(BG_LOOPER), getDependency(MetricsLogger.class)));
315 
316         mProviders.put(LightBarController.class, () -> new LightBarController(mContext));
317 
318         mProviders.put(IWindowManager.class, () -> WindowManagerGlobal.getWindowManagerService());
319 
320         mProviders.put(OverviewProxyService.class, () -> new OverviewProxyService(mContext));
321 
322         mProviders.put(EnhancedEstimates.class, () -> new EnhancedEstimatesImpl());
323 
324         mProviders.put(AppOpsListener.class, () -> new AppOpsListener(mContext));
325 
326         mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext));
327 
328         mProviders.put(IStatusBarService.class, () -> IStatusBarService.Stub.asInterface(
329                 ServiceManager.getService(Context.STATUS_BAR_SERVICE)));
330 
331         // Put all dependencies above here so the factory can override them if it wants.
332         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
333 
334         sDependency = this;
335     }
336 
337     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)338     public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
339         super.dump(fd, pw, args);
340         pw.println("Dumping existing controllers:");
341         mDependencies.values().stream().filter(obj -> obj instanceof Dumpable)
342                 .forEach(o -> ((Dumpable) o).dump(fd, pw, args));
343     }
344 
345     @Override
onConfigurationChanged(Configuration newConfig)346     protected synchronized void onConfigurationChanged(Configuration newConfig) {
347         super.onConfigurationChanged(newConfig);
348         mDependencies.values().stream().filter(obj -> obj instanceof ConfigurationChangedReceiver)
349                 .forEach(o -> ((ConfigurationChangedReceiver) o).onConfigurationChanged(newConfig));
350     }
351 
getDependency(Class<T> cls)352     protected final <T> T getDependency(Class<T> cls) {
353         return getDependencyInner(cls);
354     }
355 
getDependency(DependencyKey<T> key)356     protected final <T> T getDependency(DependencyKey<T> key) {
357         return getDependencyInner(key);
358     }
359 
getDependencyInner(Object key)360     private synchronized <T> T getDependencyInner(Object key) {
361         @SuppressWarnings("unchecked")
362         T obj = (T) mDependencies.get(key);
363         if (obj == null) {
364             obj = createDependency(key);
365             mDependencies.put(key, obj);
366         }
367         return obj;
368     }
369 
370     @VisibleForTesting
createDependency(Object cls)371     protected <T> T createDependency(Object cls) {
372         Preconditions.checkArgument(cls instanceof DependencyKey<?> || cls instanceof Class<?>);
373 
374         @SuppressWarnings("unchecked")
375         DependencyProvider<T> provider = mProviders.get(cls);
376         if (provider == null) {
377             throw new IllegalArgumentException("Unsupported dependency " + cls
378                     + ". " + mProviders.size() + " providers known.");
379         }
380         return provider.createDependency();
381     }
382 
383     private static Dependency sDependency;
384 
385     public interface DependencyProvider<T> {
createDependency()386         T createDependency();
387     }
388 
destroyDependency(Class<T> cls, Consumer<T> destroy)389     private <T> void destroyDependency(Class<T> cls, Consumer<T> destroy) {
390         T dep = (T) mDependencies.remove(cls);
391         if (dep != null && destroy != null) {
392             destroy.accept(dep);
393         }
394     }
395 
396     /**
397      * Used in separate processes (like tuner settings) to init the dependencies.
398      */
initDependencies(Context context)399     public static void initDependencies(Context context) {
400         if (sDependency != null) return;
401         Dependency d = new Dependency();
402         d.mContext = context;
403         d.mComponents = new HashMap<>();
404         d.start();
405     }
406 
407     /**
408      * Used in separate process teardown to ensure the context isn't leaked.
409      *
410      * TODO: Remove once PreferenceFragment doesn't reference getActivity()
411      * anymore and these context hacks are no longer needed.
412      */
clearDependencies()413     public static void clearDependencies() {
414         sDependency = null;
415     }
416 
417     /**
418      * Checks to see if a dependency is instantiated, if it is it removes it from
419      * the cache and calls the destroy callback.
420      */
destroy(Class<T> cls, Consumer<T> destroy)421     public static <T> void destroy(Class<T> cls, Consumer<T> destroy) {
422         sDependency.destroyDependency(cls, destroy);
423     }
424 
get(Class<T> cls)425     public static <T> T get(Class<T> cls) {
426         return sDependency.getDependency(cls);
427     }
428 
get(DependencyKey<T> cls)429     public static <T> T get(DependencyKey<T> cls) {
430         return sDependency.getDependency(cls);
431     }
432 
433     public static final class DependencyKey<V> {
434         private final String mDisplayName;
435 
DependencyKey(String displayName)436         public DependencyKey(String displayName) {
437             mDisplayName = displayName;
438         }
439 
440         @Override
toString()441         public String toString() {
442             return mDisplayName;
443         }
444     }
445 }
446