SystemUI的秘密
路径:frameworks/base/packages/SystemUI
其实SystemUI就是个APP,主要功能如下
- 状态栏信息显示,比如电池,wifi/信号
- 通知面板,比如系统消息,第三方应用消息
- 近期任务栏显示面板,比如长按近期任务快捷键,显示近期使用的应用
- 截图服务
- 壁纸服务....
不死的秘密
ini
<application
android:name=".SystemUIApplication"
android:persistent="true"
android:allowClearUserData="false"
android:backupAgent=".backup.BackupHelper"
android:killAfterRestore="false"
android:hardwareAccelerated="true"
android:label="@string/app_label"
android:icon="@drawable/icon"
android:process="com.android.systemui"
android:supportsRtl="true"
android:theme="@style/Theme.SystemUI"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
tools:replace="android:appComponentFactory"
android:appComponentFactory=".SystemUIAppComponentFactory">
android:persistent="true"
保证在挂掉以后,会被系统强行拉起来。
这里注意一下 android:appComponentFactory=".SystemUIAppComponentFactory"
后面会提到。
SystemUI的启动
- SystemServer.java ->startOtherServices->startSystemUi(context, windowManagerF);
其实这里我们就看SystemUI其实是一个服务,因为启动的时候是startService
java
private static void startSystemUi(Context context, WindowManagerService windowManager) {
PackageManagerInternal pm = LocalServices.*getService*(PackageManagerInternal.class);
Intent intent = new Intent();
//pm.getSystemUiServiceComponent() 这里其实就是获得了组件路径
intent.setComponent(pm.getSystemUiServiceComponent());
intent.addFlags(Intent.*FLAG_DEBUG_TRIAGED_MISSING*);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.*SYSTEM*);
windowManager.onSystemUiStarted();
}
java
@Override
public ComponentName getSystemUiServiceComponent() {
return ComponentName.*unflattenFromString*(mContext.getResources().getString(
com.android.internal.R.string.config_systemUIServiceComponent));
}
路径 :frameworks/base/core/res/res/values/config.xml
xml
<!-- SystemUi service component -->
<string name="config_systemUIServiceComponent" translatable="false"
>com.android.systemui/com.android.systemui.SystemUIService</string>
SystemUIService.java
java
onCreate(){
//SystemUISerice启动之前会检查 是否已经有了实例,避免多次启动。
((SystemUIApplication) getApplication()).startServicesIfNeeded();
...
startServiceAsUser(
new Intent(getApplicationContext(), SystemUIAuxiliaryDumpService.class),
UserHandle.SYSTEM);
}
SystemUIApplication.java
- implements SystemUIAppComponentFactory.ContextInitializer(注意这个接口)
java
public class SystemUIApplication extends Application implements
SystemUIAppComponentFactory.ContextInitializer {
public void startServicesIfNeeded() {
//回去要启动的服务名称 如果玩的是car 那返回值是不一样的
//路径 frameworks/base/packages/SystemUI/res/values/config.xml
String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
}
private void startServicesIfNeeded(String metricsPrefix, String[] services) {
//已经启动就返回 这里有个点要注意 String[] services 是个数组
if (mServicesStarted) {
return;
}
mServices = new SystemUI[services.length];
if (!mBootCompleteCache.isBootComplete()) {
// check to see if maybe it was already completed long before we began
// see ActivityManagerService.finishBooting()
if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
mBootCompleteCache.setBootComplete();
if (DEBUG) {
Log.v(TAG, "BOOT_COMPLETED was already sent");
}
}
}
final DumpManager dumpManager = mSysUIComponent.createDumpManager();
final int N = services.length;
for (int i = 0; i < N; i++) {
String clsName = services[i];
log.traceBegin(metricsPrefix + clsName);
long ti = System.currentTimeMillis();
try {
//反射构建
SystemUI obj = mComponentHelper.resolveSystemUI(clsName);
if (obj == null) {
//无则构建 有则无需在构建 缓存进去
Constructor constructor = Class.forName(clsName).getConstructor(Context.class);
obj = (SystemUI) constructor.newInstance(this);
}
mServices[i] = obj;
} catch (ClassNotFoundException
| NoSuchMethodException
| IllegalAccessException
| InstantiationException
| InvocationTargetException ex) {
throw new RuntimeException(ex);
}
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();//调用启动
// Warn if initialization of component takes too long
ti = System.currentTimeMillis() - ti;
if (ti > 1000) {
Log.w(TAG, "Initialization of " + clsName + " took " + ti + " ms");
}
if (mBootCompleteCache.isBootComplete()) {
mServices[i].onBootCompleted();
}
dumpManager.registerDumpable(mServices[i].getClass().getName(), mServices[i]);
}
mSysUIComponent.getInitController().executePostInitTasks();
log.traceEnd();
//最后赋值避免多次启动
mServicesStarted = true;
}}
路径 : frameworks/base/packages/SystemUI/res/values/config.xml
xml
<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.util.NotificationChannels</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.statusbar.phone.StatusBar</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.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.AuthController</item>
<item>com.android.systemui.SliceBroadcastRelayHandler</item>
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.theme.ThemeOverlayController</item>
<item>com.android.systemui.accessibility.WindowMagnification</item>
<item>com.android.systemui.accessibility.SystemActions</item>
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.wmshell.WMShell</item>
</string-array>
第一步总结
SystemUI怎么启动的。
SystemServer启动的时候,执行run, 调用 startOtherServices(t); 调用 startSystemUi(context, windowManagerF);
启动了 SystemUIService 服务,在该服务的onCreate(),检查了是否已经启动,避免了多次启动,然后加载了需要的系统UI服务。
Factory的小秘密 (SystemUIFactory的构建)
- APP启动的基础流程。
Android应用程序的启动始于Zygote进程 fork 出一个新的子进程。对于每一个Android应用程序,其生命周期的起点可以认为是从ActivityThread
类的main()
方法开始的。以下是简化后的ActivityThread启动流程:
- 系统启动应用进程 :
- 当用户点击图标或者通过其他方式触发一个应用组件(如Activity)启动时,系统首先找到对应的Package以及进程信息。
- 如果需要,系统会通过Zygote机制fork出一个新的进程。
- 初始化ApplicationThread :
- 在新进程中,
ActivityThread
的main()
方法被调用,这是进程的实际入口点。 main()
方法中会创建一个内部类ApplicationThread
实例,这个类继承自IApplicationThread
接口,并实现了Binder通信所需的AIDL接口,它是ActivityThread与系统服务(主要是ActivityManagerService,简称AMS)之间进行跨进程通信的桥梁。
- 在新进程中,
- 绑定至AMS :
- ActivityThread将创建的ApplicationThread对象注册给AMS,这样AMS就可以通过Binder机制向该进程发送指令,包括启动、停止或重启Activity等操作。
- 创建Application实例 :
- ActivityThread接着会加载并创建应用程序定义的
Application
类实例,并调用其生命周期方法。
- ActivityThread接着会加载并创建应用程序定义的
- 启动第一个Activity :
- 当AMS决定启动某个Activity时,会通过Binder机制调用ApplicationThread的相应方法,这些方法最终会在ActivityThread的主线程中回调。
- ActivityThread接收到启动Activity的消息后,会通过一系列步骤,如准备Context、Instrumentation、Intent等,进而调用
performLaunchActivity()
方法创建并启动目标Activity。
总结来说,ActivityThread并不是由开发者直接启动的,而是由Android系统在创建新的应用程序进程时自动启动,并作为该进程的主线程运行,负责管理整个应用组件的生命周期和系统服务之间的交互。
java
Process.java -->start()
-->startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
最终启动ActivityThread的main()。
- 应用的创建 和AppComponentFactory
java
performLaunchActivity()-->
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
--> app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
// 看这块代码
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
private AppComponentFactory getFactory(String pkg) {
if (pkg == null) {
Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
return AppComponentFactory.DEFAULT;
}
//没配置则走默认 有则走对应的factory
if (mThread == null) {
Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
+ " disabling AppComponentFactory", new Throwable());
return AppComponentFactory.DEFAULT;
}
LoadedApk apk = mThread.peekPackageInfo(pkg, true);
// This is in the case of starting up "android".
if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
return apk.getAppFactory();
}
SystemUIAppComponentFactory.java
-
这里有个点 app instanceof ContextInitializer 如果你是这个接口 那么就回调了如下方法。
createFromConfig() 根据当前启动的不同 ,可能是如下之一
-
com.android.systemui.SystemUIFactory
-
com.android.systemui.tv.TvSystemUIFactory
-
com.android.systemui.CarSystemUIFactory
-
java
@NonNull
@Override
public Application instantiateApplicationCompat(
@NonNull ClassLoader cl, @NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Application app = super.instantiateApplicationCompat(cl, className);
if (app instanceof ContextInitializer) {
((ContextInitializer) app).setContextAvailableCallback(
context -> {
//回调该方法 使用dagger2完成一个注入
SystemUIFactory.createFromConfig(context);
//这里根据启动的时候的配置 可能 是 com.android.systemui.SystemUIFactory / com.android.systemui.tv.TvSystemUIFactory/ com.android.systemui.CarSystemUIFactory
SystemUIFactory.getInstance().getSysUIComponent().inject(
SystemUIAppComponentFactory.this);
}
);
}
return app;
}
再次回到SystemUIApplication
ini
public void onCreate() {
super.onCreate();
//构建注入完成 可以使用
mRootComponent = SystemUIFactory.getInstance().getRootComponent();
mSysUIComponent = SystemUIFactory.getInstance().getSysUIComponent();
mComponentHelper = mSysUIComponent.getContextComponentHelper();
mBootCompleteCache = mSysUIComponent.provideBootCacheImpl();
}
最后的总结
SystemServer启动的时候,执行run方法, 调用 startOtherServices(t); 调用 startSystemUi(context, windowManagerF);
在SystemUIApplication 创建的时候,使用了SystemUIAppComponentFactory 使用dagger2构建了SystemUIFactory。
在启动动 SystemUIService 服务,在该服务的onCreate(),检查了是否已经启动,避免了多次启动,然后加载了需要的系统UI样式。