0x00 介绍
在前文中已经知道 SystemUI 是由 SystemServer 启动的。更准确的说是 SystemServer 启动了 SystemUI 中的名为 SystemUIService 的服务,然后在 SystemUIApplication 中启动了所有服务组件。
这些服务组件在 config.xml 中定义
frameworks/base/packages/SystemUI/res/values/config.xml
<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.util.NotificationChannels</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.statusbar.phone.StatusBar</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.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.biometrics.AuthController</item>
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.theme.ThemeOverlayController</item>
<item>com.android.systemui.accessibility.WindowMagnification</item>
<item>com.android.systemui.accessibility.SystemActions</item>
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.wmshell.WMShell</item>
</string-array>
这些都是在 SystemUI 处理各种业务逻辑的关键代码,一共有20多个组件,从另外一个侧面可以看出 SystemUI 的复杂程度。
它们的介绍也可以在源码阅读官网上查看
这里简单说明一下
com.android.systemui.Dependency
提供依赖注入实现(这个在最新的源码 config_systemUIServiceComponents 里面已经是没有了,但如果你看 Android 10 这个类还是存在的)
com.android.systemui.util.NotificationChannels
用来处理通知的逻辑
com.android.systemui.keyguard.KeyguardViewMediator
用来处理键盘锁状态
com.android.systemui.recents.Recents
处理最新任务列表的逻辑
com.android.systemui.volume.VolumeUI
监听音量,并决定是否显示音量的对话框
com.android.systemui.status.phone.StatusBar
状态栏,也包含了通知栏和其它重要的 UI 交互,例如键盘锁等。这里也会监听通知
com.android.systemui.usb.StorageNotification
监听 USB 连接状态并发送通知进行提示
com.android.systemui.power.PowerUI
监听电量状态并在低电量时发送通知
com.android.systemui.media.RingtonePlayer
用于播放铃声
com.android.systemui.keyboard.KeyboardUI
键盘锁 UI
com.android.systemui.shortcut.ShortcutKeyDispatcher
向 SystemUI 组件派发快捷键
@string/config_systemUIVendorServiceComponent
这里可以定义厂商定制的组件
com.android.systemui.util.leak.GarbageMonitor$Service
用于监控内存泄漏的服务
com.android.systemui.LatencyTester
仅在 debug 环境执行,用于监听系统测试延迟的模拟动作
com.android.systemui.globalactions.GlobalActionsComponent
用于显示全局对话框(例如长按电源按键)
com.android.systemui.ScreenDecorations
Draws decorations about the screen in software (e.g. rounded corners, cutouts).
处理页面中的显示的形状(如圆角)
com.android.systemui.biometrics.BiometricDialogImpl
生物识别 UI (如指纹识别、解锁等页面?)
com.android.systemui.wmshell.WMShell
Delegates SysUI events to WM Shell controllers.
转发 SysUI 事件到 WM Shell
0x01 组件结构
这些服务组件不是 Android 系统四大组件里面的服务。这些组件在实现上都是普通的 Java 类,实际上这些组件都继承于 SystemUI 这个类
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUI.java
/**
* A top-level module of system UI code (sometimes called "system UI services" elsewhere in code).
* Which SystemUI modules are loaded can be controlled via a config resource.
*
* @see SystemUIApplication#startServicesIfNeeded()
*/
public abstract class SystemUI implements Dumpable {
protected final Context mContext;
public SystemUI(Context context) {
mContext = context;
}
public abstract void start();
protected void onConfigurationChanged(Configuration newConfig) {
}
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
}
protected void onBootCompleted() {
}
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);
}
}
可以看出这个类并不复杂,从注释中也可以知道这些组件被称为 system UI services。它是抽象的,它的 start() 是需要在子类中实现的。
从前文已经了解到每个组件是在 SystemUIApplication#startServicesIfNeeded() 中通过反射构造后,然后调用了 start() 进行启动。当然还有 onBootCompleted() 方法也见过了,它会在 SystemUIApplication#onCreate() 注册系统启动完成的监听动作,待系统启动完成后会执行这个方法。
类结构图可以参考
这里只画出了4个实现类,其它可以自行脑补
0x02 思考
了解这些有什么用?
当然如果你不是做系统应用开发,这些知识对你来说可能用处不那么大。尤其当你只是纯上层应用开发者,了解到其中大概的原理也就差不多了,根本不用深究;
但是如果你需要深度定制系统的 UI 界面,只是知道其中的大概,我觉得是不够的。
在对这些组件有了一个比较宏观的认识之后,然后能够根据需求深入理解其运行机制,接一下就可以对其改造,进行二次创造了。
0x03 引用
- 在线源码阅读 cs.android.com