1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.util.Log;
25 import android.view.ViewGroup;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.internal.widget.LockPatternUtils;
29 import com.android.keyguard.KeyguardUpdateMonitor;
30 import com.android.keyguard.ViewMediatorCallback;
31 import com.android.systemui.bubbles.BubbleController;
32 import com.android.systemui.dagger.DaggerSystemUIRootComponent;
33 import com.android.systemui.dagger.DependencyProvider;
34 import com.android.systemui.dagger.SystemUIRootComponent;
35 import com.android.systemui.keyguard.DismissCallbackRegistry;
36 import com.android.systemui.plugins.FalsingManager;
37 import com.android.systemui.plugins.statusbar.StatusBarStateController;
38 import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
39 import com.android.systemui.statusbar.NotificationListener;
40 import com.android.systemui.statusbar.NotificationMediaManager;
41 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
42 import com.android.systemui.statusbar.phone.DozeParameters;
43 import com.android.systemui.statusbar.phone.KeyguardBouncer;
44 import com.android.systemui.statusbar.phone.KeyguardBypassController;
45 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
46 import com.android.systemui.statusbar.phone.StatusBar;
47 import com.android.systemui.statusbar.policy.KeyguardStateController;
48 
49 import java.util.concurrent.Executor;
50 
51 import dagger.Module;
52 import dagger.Provides;
53 
54 /**
55  * Class factory to provide customizable SystemUI components.
56  */
57 public class SystemUIFactory {
58     private static final String TAG = "SystemUIFactory";
59 
60     static SystemUIFactory mFactory;
61     private SystemUIRootComponent mRootComponent;
62 
getInstance()63     public static <T extends SystemUIFactory> T getInstance() {
64         return (T) mFactory;
65     }
66 
createFromConfig(Context context)67     public static void createFromConfig(Context context) {
68         if (mFactory != null) {
69             return;
70         }
71 
72         final String clsName = context.getString(R.string.config_systemUIFactoryComponent);
73         if (clsName == null || clsName.length() == 0) {
74             throw new RuntimeException("No SystemUIFactory component configured");
75         }
76 
77         try {
78             Class<?> cls = null;
79             cls = context.getClassLoader().loadClass(clsName);
80             mFactory = (SystemUIFactory) cls.newInstance();
81             mFactory.init(context);
82         } catch (Throwable t) {
83             Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
84             throw new RuntimeException(t);
85         }
86     }
87 
88     @VisibleForTesting
cleanup()89     static void cleanup() {
90         mFactory = null;
91     }
92 
SystemUIFactory()93     public SystemUIFactory() {}
94 
init(Context context)95     private void init(Context context) {
96         mRootComponent = buildSystemUIRootComponent(context);
97 
98         // Every other part of our codebase currently relies on Dependency, so we
99         // really need to ensure the Dependency gets initialized early on.
100 
101         Dependency dependency = new Dependency();
102         mRootComponent.createDependency().createSystemUI(dependency);
103         dependency.start();
104     }
105 
initWithRootComponent(@onNull SystemUIRootComponent rootComponent)106     protected void initWithRootComponent(@NonNull SystemUIRootComponent rootComponent) {
107         if (mRootComponent != null) {
108             throw new RuntimeException("Root component can be set only once.");
109         }
110 
111         mRootComponent = rootComponent;
112     }
113 
buildSystemUIRootComponent(Context context)114     protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
115         return DaggerSystemUIRootComponent.builder()
116                 .dependencyProvider(new DependencyProvider())
117                 .contextHolder(new ContextHolder(context))
118                 .build();
119     }
120 
getRootComponent()121     public SystemUIRootComponent getRootComponent() {
122         return mRootComponent;
123     }
124 
125     /** Returns the list of system UI components that should be started. */
getSystemUIServiceComponents(Resources resources)126     public String[] getSystemUIServiceComponents(Resources resources) {
127         return resources.getStringArray(R.array.config_systemUIServiceComponents);
128     }
129 
130     /** Returns the list of system UI components that should be started per user. */
getSystemUIServiceComponentsPerUser(Resources resources)131     public String[] getSystemUIServiceComponentsPerUser(Resources resources) {
132         return resources.getStringArray(R.array.config_systemUIServiceComponentsPerUser);
133     }
134 
135     /**
136      * Creates an instance of ScreenshotNotificationSmartActionsProvider.
137      * This method is overridden in vendor specific implementation of Sys UI.
138      */
139     public ScreenshotNotificationSmartActionsProvider
createScreenshotNotificationSmartActionsProvider(Context context, Executor executor, Handler uiHandler)140             createScreenshotNotificationSmartActionsProvider(Context context,
141             Executor executor,
142             Handler uiHandler) {
143         return new ScreenshotNotificationSmartActionsProvider();
144     }
145 
createKeyguardBouncer(Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils, ViewGroup container, DismissCallbackRegistry dismissCallbackRegistry, KeyguardBouncer.BouncerExpansionCallback expansionCallback, KeyguardStateController keyguardStateController, FalsingManager falsingManager, KeyguardBypassController bypassController)146     public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
147             LockPatternUtils lockPatternUtils, ViewGroup container,
148             DismissCallbackRegistry dismissCallbackRegistry,
149             KeyguardBouncer.BouncerExpansionCallback expansionCallback,
150             KeyguardStateController keyguardStateController, FalsingManager falsingManager,
151             KeyguardBypassController bypassController) {
152         return new KeyguardBouncer(context, callback, lockPatternUtils, container,
153                 dismissCallbackRegistry, falsingManager,
154                 expansionCallback, keyguardStateController,
155                 Dependency.get(KeyguardUpdateMonitor.class), bypassController,
156                 new Handler(Looper.getMainLooper()));
157     }
158 
createNotificationIconAreaController(Context context, StatusBar statusBar, NotificationWakeUpCoordinator wakeUpCoordinator, KeyguardBypassController keyguardBypassController, StatusBarStateController statusBarStateController)159     public NotificationIconAreaController createNotificationIconAreaController(Context context,
160             StatusBar statusBar,
161             NotificationWakeUpCoordinator wakeUpCoordinator,
162             KeyguardBypassController keyguardBypassController,
163             StatusBarStateController statusBarStateController) {
164         return new NotificationIconAreaController(context, statusBar, statusBarStateController,
165                 wakeUpCoordinator, keyguardBypassController,
166                 Dependency.get(NotificationMediaManager.class),
167                 Dependency.get(NotificationListener.class),
168                 Dependency.get(DozeParameters.class),
169                 Dependency.get(BubbleController.class));
170     }
171 
172     @Module
173     public static class ContextHolder {
174         private Context mContext;
175 
ContextHolder(Context context)176         public ContextHolder(Context context) {
177             mContext = context;
178         }
179 
180         @Provides
provideContext()181         public Context provideContext() {
182             return mContext;
183         }
184     }
185 }
186