一、SystemUI概述
1.1 定义与作用
Android SystemUI是Android系统的重要组成部分,它负责呈现用户直接交互的界面元素,包括状态栏、导航栏、锁屏界面、通知中心等。SystemUI作为Framework层与用户之间的桥梁,不仅提供了美观易用的界面,还实现了许多核心功能,如通知管理、快捷设置、电源管理等。
1.2 架构层次
SystemUI在Android架构中属于应用层,但与Framework层紧密交互:
- 应用层:SystemUI以APK形式存在,运行在独立进程中
- Framework层:提供WindowManager、NotificationManager等核心服务
- HAL层:与硬件抽象层交互,获取屏幕、传感器等信息
- Linux内核:提供底层驱动支持
二、SystemUI启动的前置条件
2.1 Zygote进程启动
Android系统启动的第一步是Zygote进程的启动。Zygote是Android应用程序的孵化器,它会预加载常用类和资源,加速应用进程的创建。
// ZygoteInit.java
public static void main(String argv[]) {
// 1. 创建虚拟机
RuntimeInit.enableDdms();
// 2. 注册Android核心类库
Zygote.nativeZygoteInit();
// 3. 预加载类和资源
preload();
// 4. 启动SystemServer进程
startSystemServer();
// 5. 等待AMS请求创建应用进程
runSelectLoopMode();
}
2.2 SystemServer进程启动
SystemServer是Zygote孵化的第一个进程,它负责启动和管理所有系统服务:
// SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
// 1. 准备系统上下文
createSystemContext();
// 2. 启动引导服务
startBootstrapServices();
// 3. 启动核心服务
startCoreServices();
// 4. 启动其他服务
startOtherServices();
// 5. 系统服务初始化完成
SystemServerInitThreadPool.shutdown();
}
2.3 ActivityManagerService就绪
在启动SystemUI之前,ActivityManagerService(AMS)必须先完成初始化。AMS是Android系统的核心服务之一,负责管理应用程序的生命周期和Activity栈。
// ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceAndSlog t) {
// 1. 完成系统服务初始化
mSystemServiceManager.systemReady();
// 2. 启动Home应用
startHomeActivityLocked(currentUserId, "systemReady");
// 3. 启动SystemUI
startSystemUi(context, windowManagerF);
// 4. 系统准备就绪回调
goingCallback.run();
}
三、SystemUI的启动流程
3.1 AMS触发SystemUI启动
当系统准备就绪时,AMS会调用startSystemUi()
方法启动SystemUI:
// ActivityManagerService.java
private void startSystemUi(Context context, WindowManagerService wms) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
// 启动SystemUIService
context.startServiceAsUser(intent, UserHandle.SYSTEM);
}
3.2 SystemUIService启动
SystemUIService是SystemUI的入口点,它继承自Service类:
// SystemUIService.java
public class SystemUIService extends Service {
@Override
public void onCreate() {
super.onCreate();
// 1. 创建Dependency注入器
Dependency.get(DependencyInflater.class).inject(this);
// 2. 获取SystemUIApplication实例
mApplication = (SystemUIApplication) getApplication();
// 3. 启动SystemUI组件
mApplication.startServicesIfNeeded();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
3.3 SystemUI组件初始化
SystemUIApplication负责初始化各个UI组件:
// SystemUIApplication.java
public void startServicesIfNeeded() {
if (mServicesStarted) {
return;
}
// 1. 记录启动时间
long ti = System.currentTimeMillis();
// 2. 获取要启动的服务列表
String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
// 3. 启动服务
mServices = new SystemUI[names.length];
for (int i = 0; i < names.length; i++) {
final String clsName = names[i];
final Class<?> cls;
try {
// 反射加载类
cls = Class.forName(clsName);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
try {
// 创建实例
SystemUI obj = (SystemUI) cls.getConstructor(Context.class).newInstance(this);
mServices[i] = obj;
// 启动服务
obj.start();
if (DBG) Slog.d(TAG, "Started " + obj.getClass().getSimpleName());
} catch (Exception ex) {
throw new RuntimeException("Error creating " + clsName, ex);
}
}
// 4. 启动完成
mServicesStarted = true;
Slog.i(TAG, "Starting SystemUI completed in " + (System.currentTimeMillis() - ti) + "ms");
}
3.4 核心组件启动
SystemUI启动的核心组件包括:
- StatusBar:状态栏
- NavigationBar:导航栏
- NotificationPanel:通知面板
- Keyguard:锁屏界面
- VolumeUI:音量控制UI
- Recents:最近任务管理
下面是StatusBar的启动代码示例:
// PhoneStatusBar.java
@Override
public void start() {
super.start();
// 1. 创建状态栏窗口
createAndAddWindows();
// 2. 初始化通知管理
mNotificationListener = new NotificationListener(this);
mNotificationListener.registerAsSystemService();
// 3. 初始化快速设置
initQs();
// 4. 注册各种系统广播接收器
registerReceiver();
// 5. 初始化状态栏图标
setupStatusBarIconViews();
// 6. 显示状态栏
makeStatusBarVisible();
}
四、SystemUI与WindowManager的交互
4.1 WindowManagerService初始化
在SystemServer启动过程中,WindowManagerService(WMS)会被初始化:
// SystemServer.java
private void startOtherServices() {
// ...
// 启动WindowManagerService
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
// ...
}
4.2 SystemUI窗口添加
StatusBar等组件通过WMS添加窗口:
// BaseStatusBar.java
protected void createAndAddWindows() {
// 1. 创建WindowManager.LayoutParams
mStatusBarWindowLayoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
statusBarHeight,
WindowManager.LayoutParams.TYPE_STATUS_BAR,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
PixelFormat.TRANSLUCENT);
// 2. 设置窗口属性
mStatusBarWindowLayoutParams.gravity = Gravity.TOP;
mStatusBarWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
mStatusBarWindowLayoutParams.setTitle("StatusBar");
// 3. 通过WindowManager添加窗口
mWindowManager.addView(mStatusBarWindow, mStatusBarWindowLayoutParams);
}
4.3 窗口层级管理
SystemUI的窗口层级由TYPE_STATUS_BAR和TYPE_NAVIGATION_BAR等参数决定:
// WindowManagerPolicyConstants.java
public interface WindowManagerPolicyConstants {
// 状态栏窗口类型
int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW + 2;
// 导航栏窗口类型
int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 4;
// ...
}
五、SystemUI的关键功能模块
5.1 通知管理系统
通知管理是SystemUI的核心功能之一:
// NotificationListener.java
public class NotificationListener extends NotificationListenerService
implements NotificationEntryManager.NotificationListener {
@Override
public void onListenerConnected() {
// 连接到NotificationManagerService
super.onListenerConnected();
// 获取当前所有通知
Collection<StatusBarNotification> activeNotifications = getActiveNotifications();
for (StatusBarNotification sbn : activeNotifications) {
// 处理已有通知
handleNotificationPosted(sbn, null);
}
}
@Override
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
// 处理新通知
handleNotificationPosted(sbn, rankingMap);
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap, int reason) {
// 处理通知移除
handleNotificationRemoved(sbn, rankingMap, reason, null);
}
// ...
}
5.2 电源按键处理
电源按键事件的处理流程:
// PhoneWindowManager.java
@Override
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
// ...
if (keyCode == KeyEvent.KEYCODE_POWER) {
// 电源键处理
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // 不唤醒设备
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN: {
// 记录按下时间
mPowerKeyDownTime = event.getDownTime();
// 发送电源键按下广播
mPowerKeyHandled = interceptPowerKeyDown(event, interactive);
break;
}
case KeyEvent.ACTION_UP: {
final boolean handled = mPowerKeyHandled;
mPowerKeyHandled = false;
// 处理电源键释放
interceptPowerKeyUp(event, interactive, handled);
break;
}
}
}
// ...
}
5.3 导航栏手势处理
现代Android设备广泛支持导航栏手势操作:
// NavigationBarInflaterView.java
private void setupGestures() {
// 为主屏幕手势创建监听器
mHomeDragListener = new HomeDragListener(mContext, mBarService, mStatusBar,
mNavigationMode, mRotation);
// 设置触摸监听器
mContentView.setOnTouchListener(mHomeDragListener);
// 为最近任务手势创建监听器
mRecentScrubber = new RecentScrubber(mContext, mBarService, mStatusBar,
mNavigationMode, mRotation);
// 设置触摸监听器
mRecentButton.setOnTouchListener(mRecentScrubber);
}
六、SystemUI的性能优化与常见问题
6.1 启动性能优化
优化SystemUI启动速度的关键策略:
- 延迟初始化非关键组件
- 并行启动独立组件
- 减少不必要的反射调用
- 使用内存缓存避免重复加载资源
// 延迟初始化示例
private void lazyInitComponents() {
// 使用Handler.postDelayed延迟初始化非关键组件
new Handler(Looper.getMainLooper()).postDelayed(() -> {
// 初始化非关键组件
initNonCriticalComponents();
}, 500); // 延迟500ms
}
6.2 内存优化
SystemUI运行在系统进程中,内存管理尤为重要:
- 避免内存泄漏,特别是在注册广播接收器和服务连接时
- 使用弱引用存储上下文
- 优化Bitmap使用,及时回收资源
- 避免创建大对象和频繁的GC
6.3 常见问题与解决方案
-
SystemUI崩溃:
- 原因:空指针异常、资源加载失败等
- 解决方案:加强空值检查,使用try-catch保护关键代码
-
UI响应缓慢:
- 原因:主线程执行耗时操作
- 解决方案:将耗时操作放到后台线程执行
-
窗口显示异常:
- 原因:窗口层级冲突、布局参数错误
- 解决方案:检查窗口类型和布局参数,确保正确设置
七、SystemUI的自定义与扩展
7.1 自定义SystemUI组件
Android 系统中有PhoneStatusBar
类。它是 Android 框架里用于控制状态栏功能的核心组件,属于 StatusBarManagerService 的一部分,主要负责管理状态栏的 UI 显示和交互逻辑。
不过,需要注意的是,PhoneStatusBar
类属于 Android 的内部框架代码,位于com.android.systemui.statusbar.phone
包路径下,普通的 Android 应用开发无法直接访问这个类。它主要是由系统 UI 开发人员在定制 Android 系统界面时使用。
要自定义SystemUI组件,通常需要:
- 创建自定义类继承自现有组件
- 修改配置文件替换默认组件
- 重写关键方法实现自定义逻辑
下面是一个自定义状态栏的示例:
// CustomStatusBar.java
public class CustomStatusBar extends PhoneStatusBar {
public CustomStatusBar(Context context) {
super(context);
}
@Override
public void start() {
super.start();
// 添加自定义视图
addCustomView();
}
private void addCustomView() {
// 加载自定义布局
View customView = LayoutInflater.from(mContext).inflate(R.layout.custom_status_bar_view, null);
// 添加到状态栏
mStatusBarWindow.addView(customView);
}
}
7.2 修改SystemUI配置
可以通过修改config.xml
文件来改变SystemUI的行为:
<!-- res/values/config.xml -->
<resources>
<!-- 替换默认状态栏组件 -->
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.statusbar.phone.CustomStatusBar</item>
<item>com.android.systemui.navigationbar.NavigationBar</item>
<!-- 其他组件 -->
</string-array>
<!-- 修改状态栏高度 -->
<dimen name="status_bar_height">48dp</dimen>
<!-- 启用/禁用功能 -->
<bool name="config_enableNavigationBar">true</bool>
</resources>
7.3 系统级定制
对于深度定制,可能需要修改AOSP源码:
- 修改frameworks/base/packages/SystemUI目录下的代码
- 添加新的系统服务或组件
- 修改AndroidManifest.xml文件
八、总结
关键要点回顾
- SystemUI的启动依赖于Zygote、SystemServer和AMS的初始化
- SystemUI通过SystemUIService启动,并初始化各个核心组件
- SystemUI与WindowManagerService紧密协作,管理状态栏、导航栏等窗口
- SystemUI负责处理通知、电源键、导航手势等核心交互功能
- 性能优化对SystemUI至关重要,直接影响用户体验
理解SystemUI的启动流程和工作原理,不仅有助于开发者进行系统级定制和优化,还能为用户提供更加流畅、个性化的Android体验。