• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.Nullable;
18 import android.os.Handler;
19 import android.os.Looper;
20 import android.util.ArrayMap;
21 
22 import com.android.internal.annotations.VisibleForTesting;
23 import com.android.internal.logging.MetricsLogger;
24 import com.android.internal.logging.UiEventLogger;
25 import com.android.internal.util.Preconditions;
26 import com.android.keyguard.KeyguardUpdateMonitor;
27 import com.android.systemui.animation.DialogTransitionAnimator;
28 import com.android.systemui.assist.AssistManager;
29 import com.android.systemui.broadcast.BroadcastDispatcher;
30 import com.android.systemui.dagger.SysUISingleton;
31 import com.android.systemui.dagger.qualifiers.Background;
32 import com.android.systemui.dump.DumpManager;
33 import com.android.systemui.flags.FeatureFlags;
34 import com.android.systemui.fragments.FragmentService;
35 import com.android.systemui.media.NotificationMediaManager;
36 import com.android.systemui.model.SysUiState;
37 import com.android.systemui.navigationbar.NavigationBarController;
38 import com.android.systemui.navigationbar.NavigationModeController;
39 import com.android.systemui.plugins.DarkIconDispatcher;
40 import com.android.systemui.plugins.PluginManager;
41 import com.android.systemui.plugins.VolumeDialogController;
42 import com.android.systemui.plugins.statusbar.StatusBarStateController;
43 import com.android.systemui.recents.LauncherProxyService;
44 import com.android.systemui.settings.UserTracker;
45 import com.android.systemui.statusbar.CommandQueue;
46 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
47 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
48 import com.android.systemui.statusbar.notification.stack.AmbientState;
49 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
50 import com.android.systemui.statusbar.phone.LightBarController;
51 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
52 import com.android.systemui.statusbar.phone.SystemUIDialogManager;
53 import com.android.systemui.statusbar.policy.BluetoothController;
54 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
55 import com.android.systemui.statusbar.window.StatusBarWindowControllerStore;
56 import com.android.systemui.tuner.TunerService;
57 
58 import dagger.Lazy;
59 
60 import java.util.function.Consumer;
61 
62 import javax.inject.Inject;
63 import javax.inject.Named;
64 
65 /**
66  * Class to handle ugly dependencies throughout sysui until we determine the
67  * long-term dependency injection solution.
68  *
69  * Classes added here should be things that are expected to live the lifetime of sysui,
70  * and are generally applicable to many parts of sysui. They will be lazily
71  * initialized to ensure they aren't created on form factors that don't need them
72  * (e.g. HotspotController on TV). Despite being lazily initialized, it is expected
73  * that all dependencies will be gotten during sysui startup, and not during runtime
74  * to avoid jank.
75  *
76  * All classes used here are expected to manage their own lifecycle, meaning if
77  * they have no clients they should not have any registered resources like bound
78  * services, registered receivers, etc.
79  */
80 @SysUISingleton
81 public class Dependency {
82 
83     /**
84      * Key for getting a background Looper for background work.
85      */
86     private static final String BG_LOOPER_NAME = "background_looper";
87     /**
88      * Key for getting a Handler for receiving time tick broadcasts on.
89      */
90     public static final String TIME_TICK_HANDLER_NAME = "time_tick_handler";
91 
92     /**
93      * An email address to send memory leak reports to by default.
94      */
95     public static final String LEAK_REPORT_EMAIL_NAME = "leak_report_email";
96 
97     /**
98      * Whether this platform supports long-pressing notifications to show notification channel
99      * settings.
100      */
101     public static final String ALLOW_NOTIFICATION_LONG_PRESS_NAME = "allow_notif_longpress";
102 
103     /**
104      * Key for getting a background Looper for background work.
105      */
106     public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>(BG_LOOPER_NAME);
107     /**
108      * Key for getting a Handler for receiving time tick broadcasts on.
109      */
110     public static final DependencyKey<Handler> TIME_TICK_HANDLER =
111             new DependencyKey<>(TIME_TICK_HANDLER_NAME);
112 
113     private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();
114     private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();
115 
116     @Inject DumpManager mDumpManager;
117 
118     @Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher;
119     @Inject Lazy<BluetoothController> mBluetoothController;
120     @Inject Lazy<KeyguardUpdateMonitor> mKeyguardUpdateMonitor;
121     @Inject Lazy<DeviceProvisionedController> mDeviceProvisionedController;
122     @Inject Lazy<PluginManager> mPluginManager;
123     @Inject Lazy<AssistManager> mAssistManager;
124     @Inject Lazy<TunerService> mTunerService;
125     @Inject Lazy<DarkIconDispatcher> mDarkIconDispatcher;
126     @Inject Lazy<FragmentService> mFragmentService;
127     @Nullable
128     @Inject Lazy<VolumeDialogController> mVolumeDialogController;
129     @Inject Lazy<MetricsLogger> mMetricsLogger;
130     @Inject Lazy<UiOffloadThread> mUiOffloadThread;
131     @Inject Lazy<LightBarController> mLightBarController;
132     @Inject Lazy<LauncherProxyService> mLauncherProxyService;
133     @Inject Lazy<NavigationModeController> mNavBarModeController;
134     @Inject Lazy<NavigationBarController> mNavigationBarController;
135     @Inject Lazy<StatusBarStateController> mStatusBarStateController;
136     @Inject Lazy<NotificationMediaManager> mNotificationMediaManager;
137     @Inject @Background Lazy<Looper> mBgLooper;
138     @Inject @Named(TIME_TICK_HANDLER_NAME) Lazy<Handler> mTimeTickHandler;
139     @Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
140     @Inject Lazy<CommandQueue> mCommandQueue;
141     @Inject Lazy<UiEventLogger> mUiEventLogger;
142     @Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
143     @Inject Lazy<NotificationSectionsManager> mNotificationSectionsManagerLazy;
144     @Inject Lazy<ScreenOffAnimationController> mScreenOffAnimationController;
145     @Inject Lazy<AmbientState> mAmbientStateLazy;
146     @Inject Lazy<GroupMembershipManager> mGroupMembershipManagerLazy;
147     @Inject Lazy<GroupExpansionManager> mGroupExpansionManagerLazy;
148     @Inject Lazy<SystemUIDialogManager> mSystemUIDialogManagerLazy;
149     @Inject Lazy<DialogTransitionAnimator> mDialogTransitionAnimatorLazy;
150     @Inject Lazy<UserTracker> mUserTrackerLazy;
151     @Inject Lazy<StatusBarWindowControllerStore> mStatusBarWindowControllerStoreLazy;
152 
153     @Inject
Dependency()154     public Dependency() {
155     }
156 
157     /**
158      * Initialize Depenency.
159      */
start()160     protected void start() {
161         // TODO: Think about ways to push these creation rules out of Dependency to cut down
162         // on imports.
163         mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get);
164         mProviders.put(BG_LOOPER, mBgLooper::get);
165         mProviders.put(BroadcastDispatcher.class, mBroadcastDispatcher::get);
166         mProviders.put(BluetoothController.class, mBluetoothController::get);
167         mProviders.put(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor::get);
168         mProviders.put(DeviceProvisionedController.class, mDeviceProvisionedController::get);
169         mProviders.put(PluginManager.class, mPluginManager::get);
170         mProviders.put(AssistManager.class, mAssistManager::get);
171         mProviders.put(TunerService.class, mTunerService::get);
172         mProviders.put(DarkIconDispatcher.class, mDarkIconDispatcher::get);
173         mProviders.put(FragmentService.class, mFragmentService::get);
174         mProviders.put(VolumeDialogController.class, mVolumeDialogController::get);
175         mProviders.put(MetricsLogger.class, mMetricsLogger::get);
176         mProviders.put(UiOffloadThread.class, mUiOffloadThread::get);
177         mProviders.put(LightBarController.class, mLightBarController::get);
178         mProviders.put(LauncherProxyService.class, mLauncherProxyService::get);
179         mProviders.put(NavigationModeController.class, mNavBarModeController::get);
180         mProviders.put(NavigationBarController.class, mNavigationBarController::get);
181         mProviders.put(StatusBarStateController.class, mStatusBarStateController::get);
182         mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get);
183         mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
184         mProviders.put(CommandQueue.class, mCommandQueue::get);
185         mProviders.put(UiEventLogger.class, mUiEventLogger::get);
186         mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
187         mProviders.put(NotificationSectionsManager.class, mNotificationSectionsManagerLazy::get);
188         mProviders.put(ScreenOffAnimationController.class, mScreenOffAnimationController::get);
189         mProviders.put(AmbientState.class, mAmbientStateLazy::get);
190         mProviders.put(GroupMembershipManager.class, mGroupMembershipManagerLazy::get);
191         mProviders.put(GroupExpansionManager.class, mGroupExpansionManagerLazy::get);
192         mProviders.put(SystemUIDialogManager.class, mSystemUIDialogManagerLazy::get);
193         mProviders.put(DialogTransitionAnimator.class, mDialogTransitionAnimatorLazy::get);
194         mProviders.put(UserTracker.class, mUserTrackerLazy::get);
195         mProviders.put(
196                 StatusBarWindowControllerStore.class, mStatusBarWindowControllerStoreLazy::get);
197 
198         Dependency.setInstance(this);
199     }
200 
201     @VisibleForTesting
setInstance(Dependency dependency)202     public static void setInstance(Dependency dependency) {
203         sDependency = dependency;
204     }
205 
getDependency(Class<T> cls)206     protected final <T> T getDependency(Class<T> cls) {
207         return getDependencyInner(cls);
208     }
209 
getDependency(DependencyKey<T> key)210     protected final <T> T getDependency(DependencyKey<T> key) {
211         return getDependencyInner(key);
212     }
213 
getDependencyInner(Object key)214     private synchronized <T> T getDependencyInner(Object key) {
215         @SuppressWarnings("unchecked")
216         T obj = (T) mDependencies.get(key);
217         if (obj == null) {
218             obj = createDependency(key);
219             mDependencies.put(key, obj);
220         }
221         return obj;
222     }
223 
224     @VisibleForTesting
createDependency(Object cls)225     public <T> T createDependency(Object cls) {
226         Preconditions.checkArgument(cls instanceof DependencyKey<?> || cls instanceof Class<?>);
227 
228         @SuppressWarnings("unchecked")
229         LazyDependencyCreator<T> provider = mProviders.get(cls);
230         if (provider == null) {
231             throw new IllegalArgumentException("Unsupported dependency " + cls
232                     + ". " + mProviders.size() + " providers known.");
233         }
234         return provider.createDependency();
235     }
236 
237     private static Dependency sDependency;
238 
239     /**
240      * Interface for a class that can create a dependency. Used to implement laziness
241      * @param <T> The type of the dependency being created
242      */
243     private interface LazyDependencyCreator<T> {
createDependency()244         T createDependency();
245     }
246 
destroyDependency(Class<T> cls, Consumer<T> destroy)247     private <T> void destroyDependency(Class<T> cls, Consumer<T> destroy) {
248         T dep = (T) mDependencies.remove(cls);
249         if (dep instanceof Dumpable) {
250             mDumpManager.unregisterDumpable(dep.getClass().getName());
251         }
252         if (dep != null && destroy != null) {
253             destroy.accept(dep);
254         }
255     }
256 
257     /**
258      * Used in separate process teardown to ensure the context isn't leaked.
259      *
260      * TODO: Remove once PreferenceFragment doesn't reference getActivity()
261      * anymore and these context hacks are no longer needed.
262      */
clearDependencies()263     public static void clearDependencies() {
264         sDependency = null;
265     }
266 
267     /**
268      * Checks to see if a dependency is instantiated, if it is it removes it from
269      * the cache and calls the destroy callback.
270      */
destroy(Class<T> cls, Consumer<T> destroy)271     public static <T> void destroy(Class<T> cls, Consumer<T> destroy) {
272         sDependency.destroyDependency(cls, destroy);
273     }
274 
275     /**
276      * @deprecated see docs/dagger.md
277      */
278     @Deprecated
get(Class<T> cls)279     public static <T> T get(Class<T> cls) {
280         return sDependency.getDependency(cls);
281     }
282 
283     /**
284      * @deprecated see docs/dagger.md
285      */
286     @Deprecated
get(DependencyKey<T> cls)287     public static <T> T get(DependencyKey<T> cls) {
288         return sDependency.getDependency(cls);
289     }
290 
291     public static final class DependencyKey<V> {
292         private final String mDisplayName;
293 
DependencyKey(String displayName)294         public DependencyKey(String displayName) {
295             mDisplayName = displayName;
296         }
297 
298         @Override
toString()299         public String toString() {
300             return mDisplayName;
301         }
302     }
303 }
304