SystemUI 启动与组成机制

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、锁屏等系统级界面。
相关推荐
黄林晴2 小时前
Kotlin 2.4.0 正式稳定!Android 升级、Compose、KMP 全变化详解
android·kotlin
恋猫de小郭3 小时前
Android 官方给 Compose 搞了个不需要 UI 环境的 Composable
android·前端·flutter
珊瑚里的鱼5 小时前
C++的强制类型转换
android·开发语言·c++
问心无愧05135 小时前
ctf show web入门102
android·java·前端·笔记
Kapaseker6 小时前
Kotlin 相等的奥义
android·kotlin
Lyyaoo.6 小时前
【MySQL】锁机制
android·数据库·mysql
DS随心转插件6 小时前
DeepSeek 代码手机端导出与 AI 辅助方案实测
android·人工智能·chatgpt·智能手机·deepseek·ai导出鸭
JohnnyDeng946 小时前
【Android】Flow vs LiveData:选型指南与迁移实践
android·kotlin·livedata·flow
plainGeekDev6 小时前
线程安全集合 → 协程安全替代
android·java·kotlin