SystemUI作为系统应用,在开机的时候就会开始加载启动,今天来学习一下它的启动流程。
SystemServer.java (frameworks\base\services\java\com\android\server)
1.最开始会调用SystemServer里面的StartOtherService方法,我们可以看到startSystemUi方法实际上是启动了一个SystemUIService的服务。
private void startOtherServices() {
........
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
......
}
static final 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到这里还没有启动成功,因为startOtherService()方法都还没有执行完毕。所以暂时还不会发送ACTION_BOOT_COMPLETE广播,该广播是在AMS中的finishBooting()中发送的。(该广播在我们SystemUIService中有做监听,用来判断是否完成系统启动)。
2.现在我们来看一下SystemUIService的里面的onCreate方法,实际上又调用了SystemUIApplication里面的startServicesIfNeeded方法。
SystemUIService.java (frameworks\base\packages\systemui\src\com\android\systemui)
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
// For debugging RescueParty
if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
throw new RuntimeException();
}
}
3.这里面把SystemUIApplication的onCreate方法都贴上了,大致的操作就是判断是否加载完成。
SystemUIApplication.java (frameworks\base\packages\systemui\src\com\android\systemui)
这里面需要注意的是对于安卓系统来说,当一个应用启动,系统会保证其Application类是第一个被实例化的类,并且Application的onCreate方法,一定先于应用中所有的Activity,Service和BroadcastReceiver的创建。
@Override
public void onCreate() {
super.onCreate();
// Set the application theme that is inherited by all services. Note that setting the
// application theme in the manifest does only work for activities. Keep this in sync with
// the theme set there.
setTheme(R.style.Theme_SystemUI);
SystemUIFactory.createFromConfig(this);
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
//注册ACTION_BOOT_COMPLATETED广播
IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mBootCompleted) return;
if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
unregisterReceiver(this);
mBootCompleted = true;
if (mServicesStarted) {
final int N = mServices.length;
for (int i = 0; i < N; i++) {
mServices[i].onBootCompleted();
}
}
}
}, filter);
} else {
// We don't need to startServices for sub-process that is doing some tasks.
// (screenshots, sweetsweetdesserts or tuner ..)
String processName = ActivityThread.currentProcessName();
ApplicationInfo info = getApplicationInfo();
if (processName != null && processName.startsWith(info.processName + ":")) {
return;
}
// For a secondary user, boot-completed will never be called because it has already
// been broadcasted on startup for the primary SystemUI process. Instead, for
// components which require the SystemUI component to be initialized per-user, we
// start those components now for the current non-system user.
startServicesIfNeeded(SERVICES_PER_USER);
}
}
我们在接着看startServicesIfNeeded方法,这里面就是把对应的服务启动起来。这里的服务不是Android的service,它们其实是一个普通的java文件,里面的start方法是用来进行一些初始化操作
private void startServicesIfNeeded(Class>[] services) {
......
final int N = services.length;
for (int i = 0; i < N; i++) {
mServices[i].start();//启动对应的服务
}
......
mServicesStarted = true;
}
需要启动的服务:
private final Class>[] SERVICES = new Class[] {
Dependency.class,
NotificationChannels.class,
CommandQueue.CommandQueueStart.class,
KeyguardViewMediator.class,
Recents.class,
VolumeUI.class,
Divider.class,
SystemBars.class,
StorageNotification.class,
PowerUI.class,
RingtonePlayer.class,
KeyboardUI.class,
PipUI.class,
ShortcutKeyDispatcher.class,
VendorServices.class,
GarbageMonitor.Service.class,
LatencyTester.class,
GlobalActionsComponent.class,
RoundedCorners.class,
};
4.我们以启动SystemBars为例子,可以看到会调用mStatusBar.start(),来启动StatusBar。
SystemBars.java (frameworks\base\packages\systemui\src\com\android\systemui)
@Override
public void start() {
if (DEBUG) Log.d(TAG, "start");
createStatusBarFromConfig();
}
private void createStatusBarFromConfig() {
if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
//com.android.systemui.statusbar.phone.StatusBar
final String clsName = mContext.getString(R.string.config_statusBarComponent);
if (clsName == null || clsName.length() == 0) {
throw andLog("No status bar component configured", null);
}
Class> cls = null;
try {
cls = mContext.getClassLoader().loadClass(clsName);
} catch (Throwable t) {
throw andLog("Error loading status bar component: " + clsName, t);
}
try {
//StatusBar继承自SystemUI,反射生成的为StatusBar类型对象,引用为SystemUI类型引用
mStatusBar = (SystemUI) cls.newInstance();
} catch (Throwable t) {
throw andLog("Error creating status bar component: " + clsName, t);
}
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mComponents;
//在这里调用的statusBar的start方法
mStatusBar.start();
if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}
5.在这里面我们就不做过多的阐述了,通过调用StatusBar里面的start方法来加载Statusbar上面的资源。
StatusBar.java (frameworks\base\packages\systemui\src\com\android\systemui\statusbar\phone)
可以查看之前的文章继续看流程。
Android 8.1 中Systemui中的常见修改(六)NavigationBar加载流程
这里,要注意的是SystemBars和StatusBar类都是继承自SystemUI,前者用于在systemui进程启动时和SystemUIApplication进行交互,并且包含一个SystemUI属性,用来指向一个StatusBar对象,并start()该对象。总结一下SystemBars的作用
在SystemUIApplication中通过反射得到SystemBars实例
通过反射得到StatusBar实例
start StatusBar实例
下面是SystemUIService的执行log