1. SystemUI 是什么
SystemUI 是 Android 系统界面进程,包名通常是:
text
com.android.systemui
它负责承载 Android 系统中大量用户可见的系统级 UI,例如:
- 状态栏
- 通知栏 / Notification Shade
- 快捷设置 QS
- 锁屏 Keyguard
- 截屏界面
- 音量面板
- 媒体输出面板
- USB 调试授权弹窗
- 屏幕录制入口
- 前台服务提示
- 部分系统级弹窗
这些 UI 大多数不是普通 Activity 页面,而是由 SystemUI 进程创建 View,再通过 WindowManager 添加为系统窗口。
一句话概括:
text
SystemUI 是一个由 system_server 拉起的、常驻的、拥有系统窗口权限的系统 UI 进程。
2. SystemUIService 运行在哪个进程
SystemUIService 不运行在 system_server 进程中,而是运行在 SystemUI 自己的进程中。
在 AndroidManifest.xml 中,SystemUI 的 application 通常声明为:
xml
<application
android:name=".SystemUIApplication"
android:process="com.android.systemui"
...>
而 SystemUIService 自己没有单独声明 android:process:
xml
<service
android:name="SystemUIService"
android:exported="true" />
所以它继承 application 的进程配置,运行在:
text
com.android.systemui
也就是说:
text
system_server 负责发起启动请求,
SystemUIService 真正运行在 com.android.systemui 进程中。
3. 从 system_server 启动 SystemUIService
Android 开机过程中,system_server 会启动 AMS、WMS、PMS、NMS 等核心系统服务。
当系统服务准备到一定阶段后,system_server 会发起启动 SystemUI 的请求,目标就是:
text
com.android.systemui/.SystemUIService
整体流程可以简化为:
text
SystemServer
-> Context.startServiceAsUser()
-> ActivityManagerService
-> 如果 com.android.systemui 进程不存在,请求 Zygote fork
-> Zygote 创建 com.android.systemui 进程
-> 创建 SystemUIApplication
-> 创建 SystemUIService
-> 执行 SystemUIService.onCreate()
所以不是"先天然存在 SystemUI 进程,然后再通信创建 SystemUIService"。
更准确地说:
text
system_server 请求启动 SystemUIService;
AMS 发现目标进程不存在时,会先创建 com.android.systemui 进程;
然后在这个进程中创建 Application 和 Service。
4. SystemUIApplication 和 SystemUIService 的关系
SystemUI 进程启动后,首先会创建:
text
SystemUIApplication
它是 SystemUI 进程的 Application 对象,提供进程级 Context、基础环境初始化、依赖注入入口等。
随后创建:
text
SystemUIService
SystemUIService 更像 SystemUI 的服务启动入口,它本身并不直接承担所有 UI 的业务逻辑。
可以理解为:
text
SystemUIApplication
-> SystemUI 进程级 Application
SystemUIService
-> SystemUI 组件启动入口
具体组件
-> 状态栏、通知栏、QS、锁屏、音量面板等真正功能实现
现代 Android 中,SystemUI 内部通常通过 Dagger、CoreStartable、配置列表等方式组织各个组件的启动。
5. SystemUI 的核心组成
SystemUI 不是单一页面,而是一组系统 UI 模块的集合。
5.1 状态栏
状态栏负责显示:
- 时间
- 电量
- 信号
- Wi-Fi
- 通知图标
- 系统状态图标
状态栏不是普通 App 的 Activity 页面,而是 SystemUI 进程中的 View,被添加为系统窗口显示在屏幕顶部。
5.2 通知栏 / Notification Shade
通知栏,也就是从顶部下拉出来的通知面板,同样属于 SystemUI。
应用发送通知后,通知数据不会直接显示在应用自己的窗口里,而是先进入 system_server 中的 NotificationManagerService,再由 SystemUI 获取并渲染。
简化流程:
text
App
-> NotificationManager.notify()
-> NotificationManagerService
-> SystemUI 通知管线
-> Notification Shade 中的通知 View
5.3 QS 快捷设置
QS 是 Quick Settings,也就是快捷设置面板。
例如:
- Wi-Fi
- 蓝牙
- 手电筒
- 飞行模式
- 屏幕录制
- 亮度条
QS 通常和通知 Shade 处在同一套下拉面板结构里,由 SystemUI 自己维护状态、布局和交互。
5.4 Keyguard 锁屏
锁屏界面也是 SystemUI 的重要组成部分。
Keyguard 会和多个系统服务交互,例如:
- WindowManagerService
- PowerManagerService
- TrustManagerService
- DevicePolicyManagerService
- BiometricService
锁屏虽然看起来像一个独立页面,但它本质上也是 SystemUI 体系中的系统级 UI。
5.5 其他系统 UI
除了状态栏、通知栏和锁屏,SystemUI 还包含很多系统级界面,例如:
- 截屏浮窗
- 音量面板
- 媒体输出选择器
- USB 调试授权弹窗
- 前台服务提示
- 屏幕录制入口
- 控制中心相关界面
这些界面根据场景不同,可能是 Activity,也可能是 Dialog、Window、Overlay 或 Service 驱动的 View。
6. 为什么状态栏和下拉框没有普通页面
普通 App 显示界面通常依赖 Activity。
典型结构是:
text
Activity
-> PhoneWindow
-> DecorView
-> ContentView
-> XML layout
但是 SystemUI 不完全依赖 Activity。
SystemUI 拥有系统权限,可以直接通过 WindowManager 添加系统窗口:
text
SystemUI 组件创建 View
-> WindowManager.addView()
-> WindowManagerService 管理窗口
-> 创建 Surface
-> SurfaceFlinger 合成显示
所以状态栏、通知栏、QS 等并不是通过打开某个 Activity 页面显示的,而是:
text
SystemUI 进程创建 View,
然后作为系统窗口挂到 WindowManager。
这也是为什么状态栏、通知栏可以覆盖在所有 App 上方。
7. "挂到系统"是什么意思
"挂到系统"不是把 SystemUI 的 View 塞进某个全局 ViewGroup。
更准确地说,是 SystemUI 通过 WindowManager 向系统注册一个窗口。
完整链路可以理解为:
text
SystemUI 进程
-> WindowManager.addView(view, layoutParams)
-> ViewRootImpl / WindowManagerGlobal
-> Binder IPC
-> system_server 中的 WindowManagerService
-> 创建 WindowState
-> 管理窗口层级、位置、Insets、输入区域、权限
-> 创建 Surface / SurfaceControl
-> SystemUI 渲染 View 到 Surface Buffer
-> SurfaceFlinger 合成多个 Layer
-> 显示到屏幕
所以 SystemUI 的状态栏不是画在应用自己的窗口里,而是独立的系统窗口。
SurfaceFlinger 最终会合成多个图层,例如:
text
App Layer
StatusBar Layer
NavigationBar Layer
InputMethod Layer
Popup Layer
这些图层会按照 Z-order、透明度、裁剪区域、变换矩阵等规则合成到最终屏幕画面。
8. App DecorView 里的状态栏区域和 SystemUI 状态栏的关系
普通 App 的布局结构大致是:
text
Activity
-> PhoneWindow
-> DecorView
-> ContentView,也就是 setContentView 加载的 XML
App 的 DecorView 里可能会看到和状态栏相关的区域,比如状态栏背景、Insets 占位、padding 处理等。
但这不等于状态栏本身。
两者关系是:
text
App DecorView 的状态栏区域
-> 负责避让系统栏、绘制状态栏背景色、处理 Insets
SystemUI 状态栏
-> 负责真正显示时间、电量、信号、通知图标
也就是说:
text
App 负责"让出位置"或者"画背景";
SystemUI 负责"画状态栏内容"。
普通非全屏 App 中,内容区域通常会避开状态栏:
text
屏幕顶部:SystemUI 状态栏
下面区域:App 内容
如果 App 开启 edge-to-edge 或沉浸式,App 内容可以延伸到状态栏背后:
text
屏幕顶部:SystemUI 状态栏图标
状态栏背后:App 自己的内容或背景
此时状态栏图标仍然来自 SystemUI,而不是 App 自己绘制的。
9. 游戏全屏时为什么状态栏消失
游戏或视频类应用通常会请求隐藏系统栏。
常见 API 包括:
java
WindowInsetsController.hide(WindowInsets.Type.statusBars());
WindowInsetsController.hide(WindowInsets.Type.systemBars());
旧接口中也可能使用:
java
View.SYSTEM_UI_FLAG_FULLSCREEN
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
系统处理流程可以简化为:
text
游戏 Activity 请求全屏 / 沉浸式
-> 请求通过 ViewRootImpl / InsetsController 传给 WMS
-> WMS 更新当前窗口的 Insets 和系统栏可见性
-> SystemUI 收到状态栏可见性变化
-> 状态栏隐藏或移出可见区域
-> 游戏窗口占满屏幕
这里不是 SystemUI 进程退出了,也不是状态栏对象不存在了。
而是:
text
SystemUI 仍然运行,
但状态栏窗口根据当前前台窗口的请求被隐藏。
很多游戏中从顶部边缘下滑,状态栏还能临时出现,这就是沉浸式模式下系统栏可以被边缘手势唤出的表现。
10. SystemUI 的 View 有没有 Context
有。
但需要区分两个概念:
text
View / Window 有 Android Context;
SurfaceFlinger 中的 Layer 没有 Java Context。
SystemUI 的状态栏、通知栏、QS 等 View,使用的是 SystemUI 进程的 Context,通常来自:
text
SystemUIApplication
SystemUIService
com.android.systemui package context
关系可以理解为:
text
SystemUI 进程
-> SystemUIApplication Context
-> SystemUIService
-> 各种 Controller
-> 创建 StatusBar View / NotificationShade View / QS View
-> WindowManager.addView()
-> 生成 Surface
-> SurfaceFlinger 合成 Layer
所以准确说:
text
SystemUI 的 View 有 Context;
最终用于合成的图层 Layer 本身没有 Android Context。
App 的 DecorView 使用 App 自己的 Context,例如:
text
com.example.game
SystemUI 状态栏 View 使用 SystemUI 的 Context,例如:
text
com.android.systemui
11. SystemUI 和 system_server 的通信
SystemUI 虽然运行在独立进程中,但它高度依赖 system_server 中的系统服务。
常见交互对象包括:
- ActivityManagerService
- WindowManagerService
- StatusBarManagerService
- NotificationManagerService
- PowerManagerService
- DisplayManagerService
- InputManagerService
- DevicePolicyManagerService
- TrustManagerService
- BiometricService
通信方式主要是 Binder。
例如:
text
SystemUI 添加窗口
-> Binder 调用 WindowManagerService
SystemUI 获取通知
-> 和 NotificationManagerService 交互
SystemUI 响应状态栏命令
-> 和 StatusBarManagerService 交互
SystemUI 显示锁屏
-> 和 WMS、Power、Keyguard 相关服务交互
所以 SystemUI 和 system_server 的关系可以概括为:
text
system_server 提供系统能力和状态管理;
SystemUI 负责把系统状态渲染成用户可见的界面。
12. 从启动到显示状态栏的完整链路
从开机到状态栏显示,可以概括为:
text
设备开机
-> Zygote 启动
-> system_server 启动
-> system_server 启动核心系统服务
-> system_server 请求启动 SystemUIService
-> AMS 创建 com.android.systemui 进程
-> SystemUIApplication 创建
-> SystemUIService 创建
-> SystemUI 初始化状态栏、通知栏、QS、锁屏等组件
-> SystemUI 通过 WindowManager 添加系统窗口
-> WMS 管理窗口层级、Insets、输入区域、权限
-> SystemUI 渲染 View 到 Surface Buffer
-> SurfaceFlinger 合成 SystemUI Layer 和 App Layer
-> 屏幕显示状态栏、通知栏等系统 UI
13. 总结
SystemUI 可以从三个层面理解。
第一,进程层面:
text
SystemUI 是 com.android.systemui 进程,不是 system_server。
第二,窗口层面:
text
状态栏、通知栏、QS 等不是普通 Activity 页面,
而是 SystemUI 添加到 WindowManager 的系统窗口。
第三,渲染层面:
text
SystemUI 自己维护 View 状态并渲染到 Surface,
SurfaceFlinger 再把 SystemUI 图层和 App 图层合成到屏幕。
最终可以用一句话总结:
text
SystemUI 是由 system_server 拉起的独立系统 UI 进程。
它通过 WindowManager 添加系统窗口,
由 WMS 管理窗口关系,
由 SurfaceFlinger 完成最终图层合成,
从而实现状态栏、通知栏、QS、锁屏等系统级界面。