系列导航 :一:全景概览与架构设计 | 二:启动流程深度解析(本文) | 三:StatusBar 状态栏 | 四:NavigationBar 导航栏 | 五:通知系统 | 六:QuickSettings | 七:Keyguard 锁屏 | 八:Recents 与其他子系统
一、SystemUI 是什么
SystemUI 全称 System User Interface ,直译为"系统用户界面"。它是 Android 系统中承载系统级交互与状态展示 的核心组件,我们日常看到的状态栏、导航栏、通知中心、锁屏界面、快捷设置面板、最近任务列表等,都属于 SystemUI 的范畴。
从技术角度看,SystemUI 是一个系统级 APK ,源码位于 frameworks/base/packages/SystemUI/ 下。
注意它不是放在 packages/apps/ 下,而是放在 frameworks/base/packages/ 下,这意味着 SystemUI 本质上属于 Framework 层 ,拥有系统签名(android:sharedUserId="android.uid.system"),可以直接与 WindowManagerService、ActivityManagerService、NotificationManagerService 等核心系统服务进行交互。
二、SystemUI 的核心职责
SystemUI 在 Android 系统中扮演着以下四个关键角色:
1. 状态呈现中心
实时展示系统关键状态信息:时间、电池电量、网络信号、Wi-Fi、蓝牙、闹钟、通知图标等。
2. 全局交互入口
提供用户与系统交互的关键通道:
- 状态栏(StatusBar):下拉通知/快捷设置、显示状态图标
- 导航栏(NavigationBar):返回、主页、最近任务(经典三键)
- 锁屏(Keyguard):安全认证(PIN/图案/密码)、紧急呼叫、通知预览
- 通知抽屉(NotificationPanel):集中管理所有应用通知
- 快捷设置面板(QuickSettings):一键开关 Wi-Fi、蓝牙、飞行模式等
3. 安全边界守护者
在锁屏状态下充当安全屏障,控制对设备的访问,管理敏感通知的显示策略。
4. 沉浸式体验协调者
管理应用全屏模式下系统栏的显示与隐藏逻辑,处理 SYSTEM_UI_FLAG_FULLSCREEN、SYSTEM_UI_FLAG_HIDE_NAVIGATION、SYSTEM_UI_FLAG_IMMERSIVE_STICKY 等标志位。
三、源码目录结构总览
frameworks/base/packages/SystemUI/
├── AndroidManifest.xml # 应用清单(系统权限声明)
├── res/ # 资源文件
│ ├── layout/ # 布局文件(状态栏、导航栏、通知面板等)
│ ├── values/ # 配置值
│ ├── drawable/ # 图标资源
│ └── anim/ # 动画资源
├── src/com/android/systemui/
│ ├── SystemUIService.java # ★ 入口 Service
│ ├── SystemUIApplication.java # ★ Application 类(定义 SERVICES 数组)
│ ├── SystemUI.java # ★ 所有子模块的抽象基类
│ ├── SystemUIFactory.java # 通过反射创建各子模块实例
│ ├── statusbar/ # 状态栏 + 导航栏(SystemBars 在此)
│ │ ├── SystemBars.java # ★ 状态栏/导航栏总控服务
│ │ ├── CommandQueue.java # ★ 命令队列(与系统服务通信)
│ │ ├── BaseStatusBar.java # 状态栏抽象基类
│ │ ├── phone/ # 手机形态状态栏
│ │ │ ├── PhoneStatusBar.java # ★ 状态栏核心
│ │ │ ├── NavigationBarView.java # ★ 导航栏视图
│ │ │ ├── StatusBarWindowView.java
│ │ │ └── ...
│ │ └── policy/ # 按键策略
│ │ └── KeyButtonView.java
│ ├── keyguard/ # 锁屏模块
│ │ ├── KeyguardViewMediator.java # ★ 锁屏调度核心
│ │ └── ...
│ ├── tuner/ # 开发者调试面板(TunerService)
│ ├── stackdivider/ # 分屏(Divider 在此)
│ │ └── Divider.java
│ ├── recents/ # 最近任务模块
│ │ ├── Recents.java
│ │ └── RecentsActivity.java
│ ├── volume/ # 音量控制模块
│ │ ├── VolumeUI.java
│ │ └── VolumeDialogController.java
│ ├── power/ # 电源管理模块
│ │ └── PowerUI.java
│ ├── qs/ # QuickSettings 快捷设置
│ │ ├── QSPanel.java
│ │ └── tiles/ # 各种 Tile 实现
│ ├── media/ # 铃声播放(RingtonePlayer)
│ ├── keyboard/ # 键盘快捷键(KeyboardUI)
│ ├── shortcut/ # 快捷键分发(ShortcutKeyDispatcher)
│ ├── tv/ # TV 形态(tv.pip.PipUI)
│ └── usb/ # USB 存储通知(StorageNotification)
└── tests/ # 测试代码
关键 :
statusbar/目录不仅管状态栏,SystemBars.java同时负责状态栏和导航栏的创建与控制;stackdivider/和tv/下的PipUI也属于子模块,目录名容易让人忽略它们。
四、AOSP7 SystemUI 子模块全景
在 AOSP7 中,SystemUI 的子模块组件列表不是 res/values/config.xml 里的 XML 字符串数组,而是硬编码 在 SystemUIApplication 里的一个 Class<?>[] 数组。启动时通过 SystemUIFactory 反射创建每个组件的实例,再逐一调用 start()。这个数组的定义如下:
源码路径 :frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
java
public class SystemUIApplication extends Application {
// ...
private final Class<?>[] SERVICES = new Class[] {
com.android.systemui.tuner.TunerService.class,
com.android.systemui.keyguard.KeyguardViewMediator.class,
com.android.systemui.recents.Recents.class,
com.android.systemui.volume.VolumeUI.class,
Divider.class,
com.android.systemui.statusbar.SystemBars.class,
com.android.systemui.usb.StorageNotification.class,
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
com.android.systemui.keyboard.KeyboardUI.class,
com.android.systemui.tv.pip.PipUI.class,
com.android.systemui.shortcut.ShortcutKeyDispatcher.class,
com.android.systemui.VendorServices.class
};
// 每个用户单独启动的子集
private final Class<?>[] SERVICES_PER_USER = new Class[] {
com.android.systemui.recents.Recents.class,
com.android.systemui.tv.pip.PipUI.class
};
}
关键设计 :
SERVICES是硬编码的Class<?>[],而非 XML 配置------子模块的增删要改这一处源码并重新编译,运行时无法动态调整;数组顺序即启动顺序。
每个组件都继承自 SystemUI 抽象基类,实现 start() 方法。
下表汇总各子模块的核心类与主要职责,按"系统栏 / 面板 / 周边子系统"的顺序排列:
| 模块 | 核心类 | 主要职责 |
|---|---|---|
| StatusBar | PhoneStatusBar |
状态栏视图、通知图标、下拉手势 |
| NavigationBar | NavigationBarView |
导航栏三键、布局管理 |
| NotificationPanel | NotificationPanelView |
通知面板展开/折叠、通知条目管理 |
| QuickSettings | QSPanel / QSTileHost |
快捷开关面板、Tile 增删改 |
| Keyguard | KeyguardViewMediator |
锁屏调度、安全认证 |
| Recents | Recents |
最近任务列表展示 |
| VolumeUI | VolumeUI |
音量调节对话框 |
| PowerUI | PowerUI |
低电量/过热警告 |
| Divider | Divider |
分屏功能适配(AOSP7 新增) |
| Screenshot | SaveImageInBackgroundTask |
截屏保存与通知 |
| RingtonePlayer | RingtonePlayer |
系统铃声播放 |
五、SystemUI 与系统服务的交互全景
SystemUI 不是一个孤立的模块,它与多个系统服务紧密协作。下图展示了核心交互关系:
┌─────────────────────────────────────────────────────────────┐
│ SystemServer 进程 │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ AMS │ │ WMS │ │NotificationManagerSvc │ │
│ └────┬─────┘ └────┬─────┘ └──────────┬───────────┘ │
│ │ │ │ │
│ ┌────┴──────────────┴───────────────────┴──────────┐ │
│ │ StatusBarManagerService │ │
│ └────────────────────────┬─────────────────────────┘ │
└───────────────────────────┼────────────────────────────────┘
│ Binder IPC
┌───────────────────────────┼────────────────────────────────┐
│ SystemUI 进程 │ │
│ ┌────────────────────────┴────────────────────────┐ │
│ │ CommandQueue │ │
│ └────────┬──────────┬──────────┬──────────────────┘ │
│ │ │ │ │
│ ┌────────┴──┐ ┌─────┴────┐ ┌──┴──────────┐ │
│ │PhoneStatus│ │ Keyguard │ │ Recents │ │
│ │ Bar │ │ ViewMed │ │ │ │
│ └───────────┘ └──────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
关键交互说明:
-
与 WMS 交互 :SystemUI 通过
WindowManager.LayoutParams创建系统级窗口(TYPE_STATUS_BAR、TYPE_NAVIGATION_BAR、TYPE_KEYGUARD_DIALOG),这些窗口具有最高显示优先级。 -
与 AMS 交互:获取当前前台应用信息、处理最近任务列表、响应系统配置变化。
-
与 NMS(NotificationManagerService)交互 :通过
StatusBarManagerService作为桥梁,NMS 将通知信息传递给 SystemUI 的CommandQueue,再由PhoneStatusBar渲染到状态栏和通知面板。 -
与 StatusBarManagerService 交互 :SystemUI 通过
CommandQueue实现了IStatusBar接口,作为 NMS 的回调,接收通知增删、系统图标更新等指令。 -
与 PhoneWindowManager 交互:处理导航栏按键事件、沉浸式模式切换、锁屏/解锁状态的协调。
六、AOSP7 SystemUI 的版本特征
相比后续版本,AOSP7 的 SystemUI 有以下显著特征:
| 特征 | AOSP7 | AOSP8+ |
|---|---|---|
| 分屏功能 | 新增 Divider 模块 |
完善 |
| 画中画(PiP) | 仅 TV 支持 | 8.0 手机全面支持 |
| 通知渠道 | 不支持 | 8.0 引入 NotificationChannel |
| 锁屏通知 | 基础支持 | 8.0+ 更细粒度控制 |
| 快捷设置 | 基础 Tile 系统 | 9.0+ 更灵活的自定义 |
七、本系列文章阅读导航
| 篇目 | 标题 | 核心内容 |
|---|---|---|
| 一 | 全景概览与架构设计(本文) | 模块定位、目录结构、子模块总览 |
| 二 | 启动流程深度解析 | SystemServer→SystemUIService→startServicesIfNeeded |
| 三 | StatusBar 状态栏源码分析 | PhoneStatusBar、makeStatusBarView、图标管理 |
| 四 | NavigationBar 导航栏与 SystemBars | NavigationBarView、KeyButtonView、沉浸式模式 |
| 五 | 通知系统:从 NMS 到 SystemUI | 通知发送接收链路、NotificationEntry、通知面板 |
| 六 | QuickSettings 快捷设置面板 | QSPanel、QSTileHost、Tile 管理 |
| 七 | Keyguard 锁屏模块深度解析 | KeyguardViewMediator、安全锁屏/滑动锁屏 |
| 八 | Recents 最近任务与其他子系统 | Recents、VolumeUI、PowerUI、Screenshot、定制实战 |
八、写给读者
如果你是第一次接触 SystemUI 源码,建议先通读本文建立全局认知,然后按照从"启动流程"到"核心模块"再到"周边子系统"的顺序逐篇阅读。每篇文章都配有源码路径、关键代码片段和架构图,建议打开 AOSP 源码对照阅读,效果更佳。
学习建议:
- 先理清
SystemUI.java基类和SystemUIApplication的启动机制 - 再深入
PhoneStatusBar理解状态栏这一核心枢纽 - 然后逐个模块突破,理解各模块之间的数据流转
- 最后尝试做一个简单的定制修改(如修改状态栏图标、添加自定义 Tile)
下一篇:AOSP7 SystemUI 源码解析(二):启动流程深度解析,我们将从 SystemServer 的
startSystemUi()开始,逐层追踪 SystemUI 的完整启动链路。