从本篇开始准备写一下关于SystemUI相关的东西,SystemUI包含的东西挺多的,顶部的StatusBar,中间的Lockscreen,底部的NavigationBar等等,可以说SystemUI就是一台手机的门面,是用户对手机系统的第一印象,非常重要
我们从SystemUI的启动开始分析,SystemUI作为一个系统Service,是在SystemServer中启动的
SystemServer.java
private void startOtherServices() {
final WindowManagerService windowManagerF = wm;
......
traceBeginAndSlog("StartSystemUI");
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
......
}
private static void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
我们可以看到,SystemUI这个service和系统普通的service启动方式一样,通过startServiceXXX,只不过它这里的用户是SYSTEM,我们看下它的intent,包名为
“com.android.systemui”,类名为"com.android.systemui.SystemUIService"。
SystemUIService.java
public class SystemUIService extends Service {
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
......
}
}
SystemUIApplication.startServicesIfNeeded
public void startServicesIfNeeded() {
String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
startServicesIfNeeded(names);
}
首先加载了一个名为config_systemUIServiceComponents的array,都是一些SystemUI的关键类,配置在config文件中
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.Dependency$DependencyCreator</item>
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</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.stackdivider.Divider</item>
<item>com.android.systemui.SystemBars</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.pip.PipUI</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.BiometricDialogImpl</item>
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
<item>com.android.systemui.SizeCompatModeActivityController</item>
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.theme.ThemeOverlayController</item>
</string-array>
接着将获取到的string数组传入startServicesIfNeeded方法
startServicesIfNeeded(names)
private void startServicesIfNeeded(String[] services) {
//如果SystemUI已经启动过了则不需要再启动
if (mServicesStarted) {
return;
}
//创建一个SystemUI类型的数组,用来存储services,这些services
//都是继承SystemUI
mServices = new SystemUI[services.length];
final int N = services.length;
//遍历services
for (int i = 0; i < N; i++) {
String clsName = services[i];
long ti = System.currentTimeMillis();
Class cls;
try {
//通过类型获取其Class对象
cls = Class.forName(clsName);
//创建实际对象
Object o = cls.newInstance();
//如果services中有实现了SystemUI.Injector接口的类则
//调用其apply方法,SystemUI.Injector继承自Function,
//这是java8新增的函数式接口
if (o instanceof SystemUI.Injector) {
o = ((SystemUI.Injector) o).apply(this);
}
//将创建的SystemUI的service添加到mServices数组
mServices[i] = (SystemUI) o;
} catch(ClassNotFoundException ex){
throw new RuntimeException(ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
}
mServices[i].mContext = this;
mServices[i].mComponents = mComponents;
//调用所有创建的类的start方法
mServices[i].start();
//监控启动SystemUI的耗时时间
ti = System.currentTimeMillis() - ti;
//单项启动超过1000ms则打印log
if (ti > 1000) {
Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms");
}
//系统启动完成则调用每个mServices的onBootCompleted方法
if (mBootCompleted) {
mServices[i].onBootCompleted();
}
}
/*
下面这一大段代码是SystemUI的插件化机制相关,本篇不分析
*/
......
mServicesStarted = true;
}
其实SystemUI的启动挺简单的,就是依次调用config_systemUIServiceComponents这个config文件中定义的类的start方法和onBootCompleted方法,如果有SystemUI相关的问题可以直接在这个config文件中去找相关模块的类,从它们的start方法开始跟代码,我们在startServicesIfNeeded方法中省略了一大段关于SystemUI插件化的代码,这部分比较负责,我会在下一篇单独跟一下此部分代码流程。