目录
一、概述:
作为Android系统核心应用,SystemUI负责反馈系统及应用状态并与用户保持大量的交互。耳熟能详的三栏:StatusBar(状态栏)、NavigationBar(导航栏)与Notification Panel(通知栏),以及Recents(近期任务界面),使用起来方便又快捷。
有一点需要说明一下,Android 10之后近期列表的显示被移到Launcher app里面了。在Launcher3的一个 类中TouchInteractionService.java IBinder mMyBinder = new IOverviewProxy.Stub() 通过AIDL的方法与systemUI通信。
大多数厂商会根据自身需求对 SystemUI
的样式进行深度定制,例如在我Redmi手机中的 SystemUI
长这样:
快捷键栏:
通知栏:
二、启动流程:
启动流程主要包括两个部分:
1.在 framework
中启动 SystemUIService
2.在 SystemUIService
中启动 SystemUI
所需的各种组件
2.1在 framework
中的流程
SystemUI
是系统应用,所以它也是一个 APK
,有入口 Application
,只不过它是由 SystemServer
进程进行启动的。
1.这个就是 SystemServer
进程的入口,它会启动很多系统相关的应用,其中就包括 SystemUI。找到它的 main 方法:
从这个方法的注释来看,SystemServer
是由 zygote
进程启动的。
2.接下来看run()
方法:
SystemServer负责系统中各种重要服务的启动,不巧,由于SystemUI的重要性,她也在被启动之列,虽然是处于“Other”的地位。
3.在startOtherServices中找到:
可以看到这里通过 PackageManagerInternal.getSystemUiServiceComponent()
获取到 SystemUIService
组件,然后通过 startServiceAsUser
方法启动了服务。
该service对应的详细参数是通过getSystemUiServiceComponent()来获取的,该方法具体实现是在PackageManagerService.java里面:
可以看到 ComonentName
是从一个内部资源文件中获取到的 com.android.internal.R.string.config_systemUIServiceComponent
这个内部可以在以下路径中搜索到
frameworks/base/core/res/res/values/config.xml
具体定义为:
这个 SystemUIService
是在 SystemUI
应用中定义的,所以接下来的流程将转到 SystemUI 应用中来。
小结一下
framework
中的 SystemServer
中 run
方法启动了系统所需要的各种服务,其中就包括 SystemUIService
。 具体是通过 PackageManagerInternal
获取到 SystemUIService
的配置名称,使用 startServiceAsUser()
来启动。
2.2在 SystemUI 中的流程:
SystemUI
在源码中路径为
frameworks/base/packages/SystemUI/
首先打开 manifest
文件看下 SystemUIService
的配置:
<application
android:name=".SystemUIApplication"
android:persistent="true"
...
android:directBootAware="true"
tools:replace="android:appComponentFactory"
android:appComponentFactory=".SystemUIAppComponentFactory">
...
// 省略代码
<!-- Broadcast receiver that gets the broadcast at boot time and starts
up everything else.
TODO: Should have an android:permission attribute
-->
<service android:name="SystemUIService"
android:exported="true"
/>
...
这里我们知道了两个信息:
1.SystemUI
的入口为 SystemUIApplication
2.
SystemUI
是 persistent
应用,即使发生了 crash
系统依然会拉起这个应用
SystemUIApplication:
查看 onCreate
方法:
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "SystemUIApplication created.");
// This line is used to setup Dagger's dependency injection and should be kept at the
// top of this method.
TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",Trace.TRACE_TAG_APP);
log.traceBegin("DependencyInjection");
mContextAvailableCallback.onContextAvailable(this);
mRootComponent = SystemUIFactory.getInstance().getRootComponent();
mSysUIComponent = SystemUIFactory.getInstance().getSysUIComponent();
mComponentHelper = mSysUIComponent.getContextComponentHelper();
mBootCompleteCache = mSysUIComponent.provideBootCacheImpl();
... // 省略代码
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
// 一般情况下走这里来,例如开关机启动系统
IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
... // 省略代码
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mBootCompleteCache.isBootComplete()) return;
if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
unregisterReceiver(this);
mBootCompleteCache.setBootComplete();
if (mServicesStarted) {
final int N = mServices.length;
for (int i = 0; i < N; i++) {
mServices[i].onBootCompleted();
}
}
}
}, bootCompletedFilter);
IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
if (!mBootCompleteCache.isBootComplete()) return;
// Update names of SystemUi notification channels
NotificationChannels.createAll(context);
}
}
}, localeChangedFilter);
} else {
// We don't need to startServices for sub-process that is doing some tasks.
// (screenshots, sweetsweetdesserts or tuner ..)
// 多用户使用走这里
... // 省略代码
startSecondaryUserServicesIfNeeded();
}
}
对于Android系统来说,当一个应用启动,系统会保证其Application类是第一个被实例化的类,并且Application的onCreate方法,一定先于应用中所有的Activity,Service和BroadcastReceiver的创建。
SystemUI中,SystemUIApplication就是第一个被实例化的类。
在其中,定义了两组服务
- 一类是所有用户共用的SystemUI服务,例如:Status Bar
- 一类是每个用户独有的服务
在SystemUIApplication中,onCreate方法被调用:主要注册一个广播接收器,用以接收BOOT_COMPLETED广播,在接收到广播后,调用各模块的函数onBootCompleted。
当SystemApplication家的onCreate执行完毕,就会去启动这个SystemUIService。此服务onCreate方法在启动时被调用。
SystemUIService:
这家伙只是个中转代理(给别人一个启动你的机会)而已,整个服务,真正干活的只有红框中的一句话。调用的是SystemUIApplication中的startServicesIfNeeded方法,转了一圈又回来了。
再次跳转到 SystemUIApplication
中:
同样地,在以下路径可以找到所有的 SystemUI
组件定义
frameworks/base/packages/SystemUI/res/values/config.xml
这个是 SystemUI
组件,这里定义了各个组件的类信息:
最终会执行到 startServicesIfNeeded(names)
带参数的方法里面,就是通过反射将各个组件构造后存在 mServices
数组里面。 mServices
是在 SystemUIApplication
中定义的,它保存了所有启动的组件。
在startServicesIfNeeded()会进行遍历来创建SystemUI子类对象,然后将实例赋值给mServices数组,接着执行start()方法,最后执行onBootCompleted();
小结一下
SystemServer
启动 SystemUIService
之后,就进入到了应用层中,SystemUIApplication
是 SystemUI
的入口,在 onCreate
方法中做了一些初始化工作,注册监听通知等操作;如果是多用户则会启动了一个组件 NotificationChannels
;然后就进入到 SystemUIService
中,它在 onCreate
方法中也是执行了 SystemUIApplication
中的 startServicesIfNeeded()
方法,并把所有的服务都存在 mServices
数组中。
SystemUI
是一个 persistent
应用,它由操作系统启动,主要流程为:
1.Android
系统在开机后会创建 SystemServer
进程,它会启动各种系统所需要的服务,其中就包括 SystemUIService
。
2.SystemUIService
启动后进入到应用层 SystemUI
中,在 SystemUIApplication
它首先会初始化监听boot completed
等通知,待系统完成启动后会通知各个组件 onBootCompleted
。
3.在进入 SystemUIService
中依然执行的 SystemUIApplication
中的startServicesIfNeeded()
无参方法启动所有 SystemUI
中的组件。
4.最终的服务启动逻辑都是在 SystemUIApplication
里面,并且都保存在 mServices
数组中。
以上就是SystemUI进程启动的主要流程,SystemUI相关的子类进行各种逻辑初始化处理都是在start()及onBootCompleted()里面进行。