SystemUI 的启动流程及初始化并介绍其功能模块。

SystemUI

  • 涉及文件
    • frameworks/base/services/java/com/android/server/SystemServer.java
    • frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
    • SystemUI/src/com/android/systemui/SystemUIService.java
    • frameworks/base/packages/SystemUI/res/values/config.xml
    • frameworks/base/packages/SystemUI/src/com/android/systemui/SysUiServiceProvider.java
    • frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUI.java

启动流程

SystemServer.startSystemUi()

SystemServer 开机时会启动 SystemUI

1
2
3
4
5
6
7
8
static final void startSystemUi(Context context, WindowManagerService windowManager) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
                                          "com.android.systemui.SystemUIService"));
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    context.startServiceAsUser(intent, UserHandle.SYSTEM);
    windowManager.onSystemUiStarted();
}

SystemUIApplication.onCreate()

 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
public void onCreate() {
    super.onCreate();
    // Set the application theme that is inherited by all services. Note that setting the
    // application theme in the manifest does only work for activities. Keep this in sync with
    // the theme set there.
    // 设置主题
    setTheme(R.style.Theme_SystemUI);

    SystemUIFactory.createFromConfig(this);

    if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
        // SYSTEM 用户
        // 监听开机广播
        IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
        // 设置优先级
        bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        // 注册开机广播接收器
        registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (mBootCompleted) return;
                    // 移除本接收器
                    unregisterReceiver(this);
                    mBootCompleted = true;
                    if (mServicesStarted) {
                        final int N = mServices.length;
                        for (int i = 0; i < N; i++) {
                            mServices[i].onBootCompleted();
                        }
                    }


                }
            }, bootCompletedFilter);
        // 监听语言改变并更新  SystemUi 的通知渠道
        IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
        registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
                        if (!mBootCompleted) return;
                        // Update names of SystemUi notification channels
                        NotificationChannels.createAll(context);
                    }
                }
            }, localeChangedFilter);
    } else {
        // We don't need to startServices for sub-process that is doing some tasks.
        // (screenshots, sweetsweetdesserts or tuner ..)
        String processName = ActivityThread.currentProcessName();
        ApplicationInfo info = getApplicationInfo();
        if (processName != null && processName.startsWith(info.processName + ":")) {
            return;
        }
        // For a secondary user, boot-completed will never be called because it has already
        // been broadcasted on startup for the primary SystemUI process.  Instead, for
        // components which require the SystemUI component to be initialized per-user, we
        // start those components now for the current non-system user.
        // 第二用户启动的服务
        startSecondaryUserServicesIfNeeded();
    }
}

SystemUIService.onCreate()

1
2
3
4
5
public void onCreate() {
    super.onCreate();
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    // ......
}

SystemUIApplication.startServicesIfNeeded()

 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
public void startServicesIfNeeded() {
    // 获取  SystemUI 所有服务类名,后面看看这个数组
    String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
    startServicesIfNeeded(names);
}

private void startServicesIfNeeded(String[] services) {
    if (mServicesStarted) {
        return;
    }
    mServices = new SystemUI[services.length];

    if (!mBootCompleted) {
        // check to see if maybe it was already completed long before we began
        // see ActivityManagerService.finishBooting()
        if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
            mBootCompleted = true;
        }
    }

    final int N = services.length;
    for (int i = 0; i < N; i++) {
        String clsName = services[i];
        long ti = System.currentTimeMillis();
        Class cls;
        try {
            // 通过反射获取服务对象
            cls = Class.forName(clsName);
            mServices[i] = (SystemUI) cls.newInstance();
        } catch(ClassNotFoundException ex){
            throw new RuntimeException(ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException ex) {
            throw new RuntimeException(ex);
        }

        // 填充对象信息并启动服务
        mServices[i].mContext = this;
        mServices[i].mComponents = mComponents;
        mServices[i].start();

        // Warn if initialization of component takes too long
        // 如果服务加载时间过程发出警告
        ti = System.currentTimeMillis() - ti;
        if (ti > 1000) {
            Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms");
        }
        if (mBootCompleted) {
            mServices[i].onBootCompleted();
        }
    }
    // 插件相关
    Dependency.get(PluginManager.class).addPluginListener(new PluginListener<OverlayPlugin>() {
            private ArraySet<OverlayPlugin> mOverlays;

            @Override
            public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
                StatusBar statusBar = getComponent(StatusBar.class);
                if (statusBar != null) {
                    plugin.setup(statusBar.getStatusBarWindow(),
                                 statusBar.getNavigationBarView());
                }
                // Lazy init.
                if (mOverlays == null) mOverlays = new ArraySet<>();
                if (plugin.holdStatusBarOpen()) {
                    mOverlays.add(plugin);
                    Dependency.get(StatusBarWindowManager.class)
                        .setStateListener(b -> mOverlays.forEach(o -> o.setCollapseDesired(b)));
                    Dependency.get(StatusBarWindowManager.class)
                        .setForcePluginOpen(mOverlays.size() != 0);

                }
            }

            @Override
            public void onPluginDisconnected(OverlayPlugin plugin) {
                mOverlays.remove(plugin);
                Dependency.get(StatusBarWindowManager.class)
                    .setForcePluginOpen(mOverlays.size() != 0);
            }
        }, OverlayPlugin.class, true /* Allow multiple plugins */);

    mServicesStarted = true;
}

时序图

SystemUI 的模块

R.array.config_systemUIServiceComponents

 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
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.Dependency</item>
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
<item>com.android.systemui.stackdivider.Divider</item>
<item>com.android.systemui.SystemBars</item>
<item>com.android.systemui.usb.StorageNotification</item>
<item>com.android.systemui.power.PowerUI</item>
<item>com.android.systemui.media.RingtonePlayer</item>
<item>com.android.systemui.keyboard.KeyboardUI</item>
<item>com.android.systemui.pip.PipUI</item>
<item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
<item>@string/config_systemUIVendorServiceComponent</item>
<item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
<item>com.android.systemui.LatencyTester</item>
<item>com.android.systemui.globalactions.GlobalActionsComponent</item>
<item>com.android.systemui.ScreenDecorations</item>
<item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
</string-array>

<string name="config_systemUIVendorServiceComponent" translatable="false">com.android.systemui.VendorServices</string>
  1. com.android.systemui.Dependency 处理依赖
  2. com.android.systemui.util.NotificationChannels 通知渠道
  3. com.android.systemui.statusbar.CommandQueue$CommandQueueStart 状态栏跨进程消息处理
  4. com.android.systemui.keyguard.KeyguardViewMediator 锁屏
  5. com.android.systemui.recents.Recents 最近任务管理
  6. com.android.systemui.volume.VolumeUI 音量调节
  7. com.android.systemui.stackdivider.Divider 分屏
  8. com.android.systemui.SystemBars 状态栏
  9. com.android.systemui.usb.StorageNotification USB 存储通知
  10. com.android.systemui.power.PowerUI 电源事件
  11. com.android.systemui.media.RingtonePlayer 铃声播放
  12. com.android.systemui.keyboard.KeyboardUI 键盘
  13. com.android.systemui.pip.PipUI 画中画
  14. com.android.systemui.shortcut.ShortcutKeyDispatcher 快捷方式
  15. com.android.systemui.VendorServices 厂商相关定制
  16. com.android.systemui.util.leak.GarbageMonitor$Service 垃圾监测器
  17. com.android.systemui.LatencyTester 延迟测试仪
  18. com.android.systemui.globalactions.GlobalActionsComponent 全局控制
  19. com.android.systemui.ScreenDecorations 屏幕装饰
  20. com.android.systemui.fingerprint.FingerprintDialogImpl 指纹
  21. com.android.systemui.SliceBroadcastRelayHandler 切片广播

R.array.config_systemUIServiceComponentsPerUser()

第二用户需要启用的服务

1
2
3
4
5
void startSecondaryUserServicesIfNeeded() {
    String[] names =
        getResources().getStringArray(R.array.config_systemUIServiceComponentsPerUser);
    startServicesIfNeeded(names);
}

除了下面 3 个外其它的服务都是所有用户共用

1
2
3
4
5
<string-array name="config_systemUIServiceComponentsPerUser" translatable="false">
<item>com.android.systemui.Dependency</item>
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.recents.Recents</item>
</string-array>

=SystemUI.class

所有 SystemUIService 都是继承自 SystemUI.class , SystemUI.class 是一个抽象类并实现了 SysUiServiceProvider 接口

 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
public abstract class SystemUI implements SysUiServiceProvider {
    public Context mContext;
    public Map<Class<?>, Object> mComponents;

    public abstract void start();

    protected void onConfigurationChanged(Configuration newConfig) {
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    }

    protected void onBootCompleted() {
    }

    @SuppressWarnings("unchecked")
    public <T> T getComponent(Class<T> interfaceType) {
        return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
    }

    public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
        if (mComponents != null) {
            mComponents.put(interfaceType, component);
        }
    }

    public static void overrideNotificationAppName(Context context, Notification.Builder n,
                                                   boolean system) {
        final Bundle extras = new Bundle();
        String appName = system
            ? context.getString(com.android.internal.R.string.notification_app_name_system)
            : context.getString(com.android.internal.R.string.notification_app_name_settings);
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName);

        n.addExtras(extras);
    }
}

public interface SysUiServiceProvider {
    <T> T getComponent(Class<T> interfaceType);

    public static <T> T getComponent(Context context, Class<T> interfaceType) {
        return ((SysUiServiceProvider) context.getApplicationContext()).getComponent(interfaceType);
    }
}