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