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