• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.app.ActivityThread;
20 import android.content.Context;
21 import android.content.res.AssetManager;
22 import android.content.res.Resources;
23 import android.os.Handler;
24 import android.util.Log;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.systemui.dagger.DaggerGlobalRootComponent;
28 import com.android.systemui.dagger.GlobalRootComponent;
29 import com.android.systemui.dagger.SysUIComponent;
30 import com.android.systemui.dagger.WMComponent;
31 import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider;
32 import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
33 import com.android.wm.shell.transition.Transitions;
34 
35 import java.util.Optional;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Executor;
38 
39 /**
40  * Class factory to provide customizable SystemUI components.
41  */
42 public class SystemUIFactory {
43     private static final String TAG = "SystemUIFactory";
44 
45     static SystemUIFactory mFactory;
46     private GlobalRootComponent mRootComponent;
47     private WMComponent mWMComponent;
48     private SysUIComponent mSysUIComponent;
49     private boolean mInitializeComponents;
50 
getInstance()51     public static <T extends SystemUIFactory> T getInstance() {
52         return (T) mFactory;
53     }
54 
createFromConfig(Context context)55     public static void createFromConfig(Context context) {
56         createFromConfig(context, false);
57     }
58 
59     @VisibleForTesting
createFromConfig(Context context, boolean fromTest)60     public static void createFromConfig(Context context, boolean fromTest) {
61         if (mFactory != null) {
62             return;
63         }
64 
65         final String clsName = context.getString(R.string.config_systemUIFactoryComponent);
66         if (clsName == null || clsName.length() == 0) {
67             throw new RuntimeException("No SystemUIFactory component configured");
68         }
69 
70         try {
71             Class<?> cls = null;
72             cls = context.getClassLoader().loadClass(clsName);
73             mFactory = (SystemUIFactory) cls.newInstance();
74             mFactory.init(context, fromTest);
75         } catch (Throwable t) {
76             Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
77             throw new RuntimeException(t);
78         }
79     }
80 
81     @VisibleForTesting
cleanup()82     static void cleanup() {
83         mFactory = null;
84     }
85 
SystemUIFactory()86     public SystemUIFactory() {}
87 
88     @VisibleForTesting
init(Context context, boolean fromTest)89     public void init(Context context, boolean fromTest)
90             throws ExecutionException, InterruptedException {
91         // Only initialize components for the main system ui process running as the primary user
92         mInitializeComponents = !fromTest
93                 && android.os.Process.myUserHandle().isSystem()
94                 && ActivityThread.currentProcessName().equals(ActivityThread.currentPackageName());
95         mRootComponent = buildGlobalRootComponent(context);
96         // Stand up WMComponent
97         mWMComponent = mRootComponent.getWMComponentBuilder().build();
98         if (mInitializeComponents) {
99             // Only initialize when not starting from tests since this currently initializes some
100             // components that shouldn't be run in the test environment
101             mWMComponent.init();
102         }
103 
104         // And finally, retrieve whatever SysUI needs from WMShell and build SysUI.
105         SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();
106         if (mInitializeComponents) {
107             // Only initialize when not starting from tests since this currently initializes some
108             // components that shouldn't be run in the test environment
109             builder = prepareSysUIComponentBuilder(builder, mWMComponent)
110                     .setPip(mWMComponent.getPip())
111                     .setLegacySplitScreen(mWMComponent.getLegacySplitScreen())
112                     .setSplitScreen(mWMComponent.getSplitScreen())
113                     .setOneHanded(mWMComponent.getOneHanded())
114                     .setBubbles(mWMComponent.getBubbles())
115                     .setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
116                     .setShellCommandHandler(mWMComponent.getShellCommandHandler())
117                     .setAppPairs(mWMComponent.getAppPairs())
118                     .setTaskViewFactory(mWMComponent.getTaskViewFactory())
119                     .setTransitions(mWMComponent.getTransitions())
120                     .setStartingSurface(mWMComponent.getStartingSurface())
121                     .setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper());
122         } else {
123             // TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
124             // is separating this logic into newly creating SystemUITestsFactory.
125             builder = prepareSysUIComponentBuilder(builder, mWMComponent)
126                     .setPip(Optional.ofNullable(null))
127                     .setLegacySplitScreen(Optional.ofNullable(null))
128                     .setSplitScreen(Optional.ofNullable(null))
129                     .setOneHanded(Optional.ofNullable(null))
130                     .setBubbles(Optional.ofNullable(null))
131                     .setHideDisplayCutout(Optional.ofNullable(null))
132                     .setShellCommandHandler(Optional.ofNullable(null))
133                     .setAppPairs(Optional.ofNullable(null))
134                     .setTaskViewFactory(Optional.ofNullable(null))
135                     .setTransitions(Transitions.createEmptyForTesting())
136                     .setStartingSurface(Optional.ofNullable(null))
137                     .setTaskSurfaceHelper(Optional.ofNullable(null));
138         }
139         mSysUIComponent = builder.build();
140         if (mInitializeComponents) {
141             mSysUIComponent.init();
142         }
143 
144         // Every other part of our codebase currently relies on Dependency, so we
145         // really need to ensure the Dependency gets initialized early on.
146         Dependency dependency = mSysUIComponent.createDependency();
147         dependency.start();
148     }
149 
150     /**
151      * Prepares the SysUIComponent builder before it is built.
152      * @param sysUIBuilder the builder provided by the root component's getSysUIComponent() method
153      * @param wm the built WMComponent from the root component's getWMComponent() method
154      */
prepareSysUIComponentBuilder( SysUIComponent.Builder sysUIBuilder, WMComponent wm)155     protected SysUIComponent.Builder prepareSysUIComponentBuilder(
156             SysUIComponent.Builder sysUIBuilder, WMComponent wm) {
157         return sysUIBuilder;
158     }
159 
buildGlobalRootComponent(Context context)160     protected GlobalRootComponent buildGlobalRootComponent(Context context) {
161         return DaggerGlobalRootComponent.builder()
162                 .context(context)
163                 .build();
164     }
165 
shouldInitializeComponents()166     protected boolean shouldInitializeComponents() {
167         return mInitializeComponents;
168     }
169 
getRootComponent()170     public GlobalRootComponent getRootComponent() {
171         return mRootComponent;
172     }
173 
getWMComponent()174     public WMComponent getWMComponent() {
175         return mWMComponent;
176     }
177 
getSysUIComponent()178     public SysUIComponent getSysUIComponent() {
179         return mSysUIComponent;
180     }
181 
182     /**
183      * Returns the list of system UI components that should be started.
184      */
getSystemUIServiceComponents(Resources resources)185     public String[] getSystemUIServiceComponents(Resources resources) {
186         return resources.getStringArray(R.array.config_systemUIServiceComponents);
187     }
188 
189     /**
190      * Returns the list of system UI components that should be started per user.
191      */
getSystemUIServiceComponentsPerUser(Resources resources)192     public String[] getSystemUIServiceComponentsPerUser(Resources resources) {
193         return resources.getStringArray(R.array.config_systemUIServiceComponentsPerUser);
194     }
195 
196     /**
197      * Creates an instance of ScreenshotNotificationSmartActionsProvider.
198      * This method is overridden in vendor specific implementation of Sys UI.
199      */
200     public ScreenshotNotificationSmartActionsProvider
createScreenshotNotificationSmartActionsProvider( Context context, Executor executor, Handler uiHandler)201                 createScreenshotNotificationSmartActionsProvider(
202                         Context context, Executor executor, Handler uiHandler) {
203         return new ScreenshotNotificationSmartActionsProvider();
204     }
205 
206     /**
207      * Creates an instance of BackGestureTfClassifierProvider.
208      * This method is overridden in vendor specific implementation of Sys UI.
209      */
createBackGestureTfClassifierProvider( AssetManager am, String modelName)210     public BackGestureTfClassifierProvider createBackGestureTfClassifierProvider(
211             AssetManager am, String modelName) {
212         return new BackGestureTfClassifierProvider();
213     }
214 }
215