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