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 start()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 dump(FileDescriptor fd, PrintWriter pw, String[] args)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 onConfigurationChanged(Configuration newConfig)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 getDependency(Class<T> cls)330 protected final <T> T getDependency(Class<T> cls) { 331 return getDependencyInner(cls); 332 } 333 getDependency(DependencyKey<T> key)334 protected final <T> T getDependency(DependencyKey<T> key) { 335 return getDependencyInner(key); 336 } 337 getDependencyInner(Object key)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 createDependency(Object cls)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> { createDependency()363 T createDependency(); 364 } 365 destroyDependency(Class<T> cls, Consumer<T> destroy)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 */ initDependencies(Context context)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 */ clearDependencies()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 */ destroy(Class<T> cls, Consumer<T> destroy)398 public static <T> void destroy(Class<T> cls, Consumer<T> destroy) { 399 sDependency.destroyDependency(cls, destroy); 400 } 401 get(Class<T> cls)402 public static <T> T get(Class<T> cls) { 403 return sDependency.getDependency(cls); 404 } 405 get(DependencyKey<T> cls)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 DependencyKey(String displayName)413 public DependencyKey(String displayName) { 414 mDisplayName = displayName; 415 } 416 417 @Override toString()418 public String toString() { 419 return mDisplayName; 420 } 421 } 422 } 423