Home | History | Annotate | Download | only in systemui
      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
    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
    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
    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 
    352     protected final <T> T getDependency(Class<T> cls) {
    353         return getDependencyInner(cls);
    354     }
    355 
    356     protected final <T> T getDependency(DependencyKey<T> key) {
    357         return getDependencyInner(key);
    358     }
    359 
    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
    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> {
    386         T createDependency();
    387     }
    388 
    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      */
    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      */
    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      */
    421     public static <T> void destroy(Class<T> cls, Consumer<T> destroy) {
    422         sDependency.destroyDependency(cls, destroy);
    423     }
    424 
    425     public static <T> T get(Class<T> cls) {
    426         return sDependency.getDependency(cls);
    427     }
    428 
    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 
    436         public DependencyKey(String displayName) {
    437             mDisplayName = displayName;
    438         }
    439 
    440         @Override
    441         public String toString() {
    442             return mDisplayName;
    443         }
    444     }
    445 }
    446