该系列文章总纲链接:专题分纲目录 Android SystemUI组件
本章关键点总结 & 说明:
说明:本章节主要涉及SystemUI的两个启动过程,开机启动和服务启动,最终是启动SystemUI子类的各个服务。
1 SystemUIService开机启动流程
SystemUI是Android系统级的UI组件。在开机启动后,SystemServer启动中 ,开始执行对应的run方法,代码实现如下:
private void run() {
//...
// Start services.
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
//...
}
在run方法中,执行了startOtherServices,当SystemServer中核心系统服务启动完成后会调用AMS的systemReady()方法通知AMS系统已经就绪。代码实现如下:
private void startOtherServices() {
//...
StatusBarManagerService statusBar = null;
INotificationManager notification = null;
//...
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
try {
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
Slog.i(TAG, "WebViewFactory preparation");
WebViewFactory.prepareWebViewInSystemServer();
try {
startSystemUi(context);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
//...
}
}
在SystemServer中startSystemUi的代码实现如下:
static final void startSystemUi(Context context) {
Intent intent = new Intent();
//设置SystemUIService作为启动目标
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
//启动SystemUIService
context.startServiceAsUser(intent, UserHandle.OWNER);
}
这里通过 context的startServiceAsUser方法进行SystemUIService的启动,至此SystemUIService服务的开机启动流程就完成了。
2 SystemUIService服务启动
SystemUIService代码并不多,代码如下:
public class SystemUIService extends Service {
//关键方法
@Override
public void onCreate() {
super.onCreate();
//从这里可以看出,分析SystemUIApplication的startServicesIfNeeded实现即可
((SystemUIApplication) getApplication()).startServicesIfNeeded();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
if (args == null || args.length == 0) {
for (SystemUI ui: services) {
pw.println("dumping service: " + ui.getClass().getName());
ui.dump(fd, pw, args);
}
} else {
String svc = args[0];
for (SystemUI ui: services) {
String name = ui.getClass().getName();
if (name.endsWith(svc)) {
ui.dump(fd, pw, args);
}
}
}
}
}
这里主要分析SystemUIService的onCreate()中startServicesIfNeeded的实现,也就是类SystemUIApplication中 startServicesIfNeeded的代码,如下所示:
public class SystemUIApplication extends Application {
//...
//成员变量SERVICES存储了各个服务的实例,数组内容如下:
private final Class<?>[] SERVICES = new Class[] {
com.android.systemui.keyguard.KeyguardViewMediator.class,
com.android.systemui.recent.Recents.class,
com.android.systemui.volume.VolumeUI.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
};
//...
private final SystemUI[] mServices = new SystemUI[SERVICES.length];
//...
public void startServicesIfNeeded() {
//如果SystemUI已经启动过了则不需要再启动
if (mServicesStarted) {
return;
}
if (!mBootCompleted) {
if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
mBootCompleted = true;
}
}
final int N = SERVICES.length;
for (int i=0; i<N; i++) {
Class<?> cl = SERVICES[i];
//...
//实例化子服务并将其存储在mServices数组中
mServices[i] = (SystemUI)cl.newInstance();
//...
//设置context,并调用start方法启动该类型的服务。
mServices[i].mContext = this;
mServices[i].mComponents = mComponents;
mServices[i].start();
if (mBootCompleted) {
mServices[i].onBootCompleted();
}
}
mServicesStarted = true;
}
//...
}
由上可见,SystemUIService是一个容器。主要为了启动以下服务:
- com.android.systemui.keyguard.KeyguardViewMediator,锁屏管理
- com.android.systemui.recent.Recents,近期应用管理
- com.android.systemui.volume.VolumeUI,显示和控制音量的变化:媒体、铃声、闹钟音量
- com.android.systemui.statusbar.SystemBars,系统 状态栏
- com.android.systemui.usb.StorageNotification,系统 通知栏
- com.android.systemui.power.PowerUI,电池模式切换
- com.android.systemui.media.RingtonePlayer,铃声播放
这些服务类有一个共同特点,均继承于SystemUI抽象类,如下:
public class KeyguardViewMediator extends SystemUI {...}
public class Recents extends SystemUI implements RecentsComponent {...}
public class VolumeUI extends SystemUI {...}
public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {...}
public class StorageNotification extends SystemUI {...}
public class PowerUI extends SystemUI {...}
public class RingtonePlayer extends SystemUI {...}
SystemUI抽象类的内部实现如下所示:
public abstract class SystemUI {
public Context mContext;
public Map<Class<?>, Object> mComponents;
public abstract void start();
protected void onConfigurationChanged(Configuration newConfig) {
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
}
protected void onBootCompleted() {
}
@SuppressWarnings("unchecked")
public <T> T getComponent(Class<T> interfaceType) {
return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
}
public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
if (mComponents != null) {
mComponents.put(interfaceType, component);
}
}
}
可以看到最关键的是start方法,因此分析抽象类SystemUI的几个实现类均从start开始即可。接下来的章节我们 分别从这些子类的start方法开始分析。