SystemUI主要完成的功能有:
(1)、Status bars
(2)、Navigation bars
(3)、Notification
(4)、Lockscreen
(5)、Quick settings
(6)、Overview(recent task switcher)
(7)VolumeUI
SystemUI的启动时在SystemServer.java中,
2384 private static void startSystemUi(Context context, WindowManagerService windowManager) {
2385 Intent intent = new Intent();
2386 intent.setComponent(new ComponentName("com.android.systemui",
2387 "com.android.systemui.SystemUIService"));
2388 intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
2389 //Slog.d(TAG, "Starting service: " + intent);
2390 context.startServiceAsUser(intent, UserHandle.SYSTEM);
2391 windowManager.onSystemUiStarted();
2392 }
SystemUI启动第一个执行的函数是什么呢?由APP的启动过程可知(如果读者不了解这个过程可自行学习),Android系统会给应用创建独立的进程,并实例化Application对象,在SystemUI源码中的AndroidManifest.xml文件可以看到下图的配置:
255 <application
256 android:name=".SystemUIApplication"
257 android:persistent="true"
258 android:allowClearUserData="false"
259 android:allowBackup="false"
260 android:hardwareAccelerated="true"
261 android:label="@string/app_label"
262 android:icon="@drawable/icon"
263 android:process="com.android.systemui"
264 android:supportsRtl="true"
265 android:theme="@style/Theme.SystemUI"
266 android:defaultToDeviceProtectedStorage="true"
267 android:directBootAware="true"
268 tools:replace="android:appComponentFactory"
269 android:appComponentFactory=".SystemUIAppComponentFactory">
270 <!-- Keep theme in sync with SystemUIApplication.onCreate().
271 Setting the theme on the application does not affect views inflated by services.
272 The application theme is set again from onCreate to take effect for those views. -->
273
274 <!-- Broadcast receiver that gets the broadcast at boot time and starts
275 up everything else.
276 TODO: Should have an android:permission attribute
277 -->
278 <service android:name="SystemUIService"
279 android:exported="true"
280 />
通过上面的配图可知,因此在启动SystemUI应用时会创建SystemUIApplication对象并回调onCreate()方法
70 @Override
71 public void onCreate() {
72 super.onCreate();
73 Log.v(TAG, "SystemUIApplication created.");
74 // This line is used to setup Dagger's dependency injection and should be kept at the
75 // top of this method.
76 TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
77 Trace.TRACE_TAG_APP);
78 log.traceBegin("DependencyInjection");
79 mContextAvailableCallback.onContextAvailable(this);
80 log.traceEnd();
81
82 // Set the application theme that is inherited by all services. Note that setting the
83 // application theme in the manifest does only work for activities. Keep this in sync with
84 // the theme set there.
85 setTheme(R.style.Theme_SystemUI);
86
87 if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
88 IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
89 bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
90 registerReceiver(new BroadcastReceiver() {
91 @Override
92 public void onReceive(Context context, Intent intent) {
93 if (mBootCompleted) return;
94
95 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
96 unregisterReceiver(this);
97 mBootCompleted = true;
98 if (mServicesStarted) {
99 final int N = mServices.length;
100 for (int i = 0; i < N; i++) {
101 mServices[i].onBootCompleted();
102 }
103 }
104
105
106 }
107 }, bootCompletedFilter);
108
109 IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
110 registerReceiver(new BroadcastReceiver() {
111 @Override
112 public void onReceive(Context context, Intent intent) {
113 if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
114 if (!mBootCompleted) return;
115 // Update names of SystemUi notification channels
116 NotificationChannels.createAll(context);
117 }
118 }
119 }, localeChangedFilter);
120 } else {
121 // We don't need to startServices for sub-process that is doing some tasks.
122 // (screenshots, sweetsweetdesserts or tuner ..)
123 String processName = ActivityThread.currentProcessName();
124 ApplicationInfo info = getApplicationInfo();
125 if (processName != null && processName.startsWith(info.processName + ":")) {
126 return;
127 }
128 // For a secondary user, boot-completed will never be called because it has already
129 // been broadcasted on startup for the primary SystemUI process. Instead, for
130 // components which require the SystemUI component to be initialized per-user, we
131 // start those components now for the current non-system user.
132 startSecondaryUserServicesIfNeeded();
133 }
134 }
SystemUIApplication的onCreate执行完之后,这个时候就到了SystemUIService里的onCreate
//SystemUIService
35 public class SystemUIService extends Service {
36
37 @Override
38 public void onCreate() {
39 super.onCreate();
40 ((SystemUIApplication) getApplication()).startServicesIfNeeded();
41
42 // For debugging RescueParty
43 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
44 throw new RuntimeException();
45 }
46
47 if (Build.IS_DEBUGGABLE) {
48 // b/71353150 - looking for leaked binder proxies
49 BinderInternal.nSetBinderProxyCountEnabled(true);
50 BinderInternal.nSetBinderProxyCountWatermarks(1000,900);
51 BinderInternal.setBinderProxyCountCallback(
52 new BinderInternal.BinderProxyLimitListener() {
53 @Override
54 public void onLimitReached(int uid) {
55 Slog.w(SystemUIApplication.TAG,
56 "uid " + uid + " sent too many Binder proxies to uid "
57 + Process.myUid());
58 }
59 }, Dependency.get(Dependency.MAIN_HANDLER));
60 }
61 }
我们可以看到,在这里第一行就是调用到SystemUIApplication的startServicesIfNeeded, 这个函数干了什么呢
//SystemUIApplication
136 /**
137 * Makes sure that all the SystemUI services are running. If they are already running, this is a
138 * no-op. This is needed to conditinally start all the services, as we only need to have it in
139 * the main process.
140 * <p>This method must only be called from the main thread.</p>
141 */
142
143 public void startServicesIfNeeded() {
144 String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
145 startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
146 }
其实这个函数的作用就是用来启动SystemUI子系统服务,前面讲到的VolumeUI、StatusBar等都有对应的service,这里可以看到names变量是从一个资源文件里获取的,我们找到这个service的定义部分.
//config.xml
282 <!-- SystemUI Services: The classes of the stuff to start. -->
283 <string-array name="config_systemUIServiceComponents" translatable="false">
284 <item>com.android.systemui.util.NotificationChannels</item>
285 <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
286 <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
287 <item>com.android.systemui.recents.Recents</item>
288 <item>com.android.systemui.volume.VolumeUI</item>
289 <item>com.android.systemui.stackdivider.Divider</item>
290 <item>com.android.systemui.SystemBars</item>
291 <item>com.android.systemui.usb.StorageNotification</item>
292 <item>com.android.systemui.power.PowerUI</item>
293 <item>com.android.systemui.media.RingtonePlayer</item>
294 <item>com.android.systemui.keyboard.KeyboardUI</item>
295 <item>com.android.systemui.pip.PipUI</item>
296 <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
297 <item>@string/config_systemUIVendorServiceComponent</item>
298 <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
299 <item>com.android.systemui.LatencyTester</item>
300 <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
301 <item>com.android.systemui.ScreenDecorations</item>
302 <item>com.android.systemui.biometrics.BiometricDialogImpl</item>
303 <item>com.android.systemui.SliceBroadcastRelayHandler</item>
304 <item>com.android.systemui.SizeCompatModeActivityController</item>
305 <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
306 <item>com.android.systemui.theme.ThemeOverlayController</item>
307 </string-array>
可以看到其实里面定义了很多service,对应不同的子功能。
184 final int N = services.length;
185 for (int i = 0; i < N; i++) {
186 String clsName = services[i];
187 if (DEBUG) Log.d(TAG, "loading: " + clsName);
188 log.traceBegin(metricsPrefix + clsName);
189 long ti = System.currentTimeMillis();
190 Class cls;
191 try {
192 cls = Class.forName(clsName);
193 Object o = cls.newInstance();
194 if (o instanceof SystemUI.Injector) {
195 o = ((SystemUI.Injector) o).apply(this);
196 }
197 mServices[i] = (SystemUI) o;
198 } catch(ClassNotFoundException ex){
199 throw new RuntimeException(ex);
200 } catch (IllegalAccessException ex) {
201 throw new RuntimeException(ex);
202 } catch (InstantiationException ex) {
203 throw new RuntimeException(ex);
204 }
205
206 mServices[i].mContext = this;
207 mServices[i].mComponents = mComponents;
208 if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
209 mServices[i].start();
210 log.traceEnd();
每个service的具体实现和功能将在下文中描述。在图6中可以看到,实例化每个对象是向上转型为SystemUI对象,config_systemUIServiceComponents的所有service统一继承了SystemUI类.
//SystemUI.java
29 public abstract class SystemUI implements SysUiServiceProvider {
30 public Context mContext;
31 public Map<Class<?>, Object> mComponents;
32
33 public abstract void start();
34
35 protected void onConfigurationChanged(Configuration newConfig) {
36 }
37
38 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
39 }
40
41 protected void onBootCompleted() {
42 }
44 @SuppressWarnings("unchecked")
45 public <T> T getComponent(Class<T> interfaceType) {
46 return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
47 }
48
49 public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
50 if (mComponents != null) {
51 mComponents.put(interfaceType, component);
52 }
53 }
54
55 public static void overrideNotificationAppName(Context context, Notification.Builder n,
56 boolean system) {
57 final Bundle extras = new Bundle();
58 String appName = system
59 ? context.getString(com.android.internal.R.string.notification_app_name_system)
60 : context.getString(com.android.internal.R.string.notification_app_name_settings);
61 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName);
62
63 n.addExtras(extras);
64 }
65
66 public interface Injector extends Function<Context, SystemUI> {
67 }
68 }
SystemUI类提供start()、onConfigurationChanged()、dump()等重要方法,每个方法在各个service中实现不一样。
至此,SystemUI的启动基本完成,从上文可知,SystemUI是系统中非常核心的应用,在Android系统开机过程中Server进程直接发起SystemUI启动,SystemUI也是固化程序,在保证系统正常运行发挥了非常重要的作用。