SystemUI 快速搞懂启动流程
不积跬步无以至千里
SystemUI,系统界面,一个系统级的应用,其中包括了很多功能模块,比如锁屏,状态栏,分屏,音量条,多任务等等,让我们一起看一下它的启动.
随着系统的启动通过调用第一个用户空间的init进程调用Zygote进程然后调用SystemServer启动各种系统服务,而我们的SystemUI在其中启动服务中的一项.
一.SystemServer中的启动
代码路径:
frameworks/base/services/java/com/android/server/SystemServer.java
1.
private void run() {
...
//AMS,PWS等等服务
startBootstrapServices();
//电量,WebView更新等等服务
startCoreServices();
//网络,WMS,震动等等服务
startOtherServices();
...
}
//其它服务
private void startOtherServices() {
...
mActivityManagerService.systemReady(() -> {
...
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
...
}
...
//启动SystemUI的代码
static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
//指定了包名类名,启动Service
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中的启动
1.应用的启动肯定是初始化Application类
代码路径:
/code/app/src/com/android/systemui/SystemUIApplication.java
主要为了注册开机广播,来获取开机完成的事件,用来作为启动各个服务的条件.
@Override
public void 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);
mContext = getApplicationContext();
SystemUIFactory.createFromConfig(this);
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
//注册开机完成的广播
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);
...
}
2.SystemUIService的初始化
代码路径:
/code/app/src/com/android/systemui/SystemUIService.java
//在onCreate中会调用SystemUIApplication的startServicesIfNeeded()的方法
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
}
3.SystemUIApplication的startServicesIfNeeded调用
代码路径:
/code/app/src/com/android/systemui/SystemUIApplication.java
/**
* Makes sure that all the SystemUI services are running. If they are already running, this is a
* no-op. This is needed to conditinally start all the services, as we only need to have it in
* the main process.
* <p>This method must only be called from the main thread.</p>
*/
public void startServicesIfNeeded() {
startServicesIfNeeded(SERVICES);
}
所有的SystemUI功能模块
/**
* The classes of the stuff to start.
*/
private final Class<?>[] SERVICES = new Class[] {
Dependency.class,//
NotificationChannels.class,//通知
CommandQueue.CommandQueueStart.class,//StatusBar的与StatusBarManagerService.java的通信
KeyguardViewMediator.class,//锁屏
Recents.class,//多任务
VolumeUI.class,//音量条
Divider.class,//分屏的窗口
SystemBars.class,//状态栏
StorageNotification.class,//贮存的插拔(SD卡,U盘),不常用
PowerUI.class,//电量
RingtonePlayer.class,//铃声
KeyboardUI.class,键盘
PipUI.class,//分屏
ShortcutKeyDispatcher.class,
VendorServices.class,
GarbageMonitor.Service.class,
LatencyTester.class,
GlobalActionsComponent.class,
RoundedCorners.class,
};
循环启动
private void startServicesIfNeeded(Class<?>[] services) {
//是否service已经启动过了
if (mServicesStarted) {
return;
}
//如果开机标志未至成功,查看prop,有可能已经完成很久了,在我们查看AMS启动完成之前
if (!mBootCompleted) {
// check to see if maybe it was already completed long before we began
// see ActivityManagerService.finishBooting()
if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
mBootCompleted = true;
if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
}
}
Log.v(TAG, "Starting SystemUI services for user " +
Process.myUserHandle().getIdentifier() + ".");
TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
Trace.TRACE_TAG_APP);
log.traceBegin("StartServices");
//服务
final int N = services.length;
for (int i = 0; i < N; i++) {
Class<?> cl = services[i];
if (DEBUG) Log.d(TAG, "loading: " + cl);
log.traceBegin("StartServices" + cl.getSimpleName());
long ti = System.currentTimeMillis();
try {
Object newService = SystemUIFactory.getInstance().createInstance(cl);
mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
}
mServices[i].mContext = this;
mServices[i].mComponents = mComponents;
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();
log.traceEnd();
// Warn if initialization of component takes too long
ti = System.currentTimeMillis() - ti;
if (ti > 1000) {
Log.w(TAG, "Initialization of " + cl.getName() + " took " + ti + " ms");
}
if (mBootCompleted) {
mServices[i].onBootCompleted();
}
}
4.所有服务的父类SystemUI.java
代码路径:
app/src/com/android/systemui/SystemUI.java
public abstract class SystemUI implements SysUiServiceProvider {
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);
}
}
public static void overrideNotificationAppName(Context context, Notification.Builder n) {
final Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
context.getString(com.android.internal.R.string.android_system_label));
n.addExtras(extras);
}
}
所有子类实现了父类的抽象方法start方法,因此调用各自的start启动逻辑.
SystemUI的初步启动流程就先到这.