> 技术文档 > Android 16系统源码_SystemUI(一)SystemUI的启动流程_com.android.systemui

Android 16系统源码_SystemUI(一)SystemUI的启动流程_com.android.systemui


前言

Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Navigation Bar,下拉通知栏,下拉快捷栏,音量调控UI,电源调控UI,近期任务界面 Recent Task 等等。
Android 16系统源码_SystemUI(一)SystemUI的启动流程_com.android.systemui
在 Andorid 系统源码中,package/apps下放的是系统内置的一些 app,例如 settings,camera,Phone,Message 等等。而在 framework/base/package 下,它们也是系统的 app,SystemUI 就在此目录下。它控制着整个Android系统的界面,但其实他也是一个 app,不同于一般的 app,它不可卸载也不可以被第三方应用替换。对于用户而言,SystemUI 的改动是最能直观感受到的。因此,每个 Android 版本在 SystemUI 上都有比较大的改动。而对开发者而言,理解 Android SystemUI 对优化Android系统界面,改善用户体验十分重要。因为SystemUI 是系统应用,所以它也是一个 APK,有入口 Application,只不过它是由 SystemServer 进程进行启动的。

一 SystemServer阶段

1.1 SystemServer启动SystemUI

在Android系统之后,init进程会启动Zygote进程,而Zygote进程又会孵化启动SystemServer进程,SystemServer的main()方法如下所示。

//frameworks/base/services/java/com/android/server/SystemServer.javapublic final class SystemServer implements Dumpable {public static void main(String[] args) { new SystemServer().run();//触发run方法}private void run(){ ...代码省略... // Start services. try { t.traceBegin(\"StartServices\"); startBootstrapServices(t);//启动引导服务 startCoreServices(t);//启动核心服务 startOtherServices(t);//启动其他服务 startApexServices(t);//启动Apex打包服务 updateWatchdogTimeout(t); CriticalEventLog.getInstance().logSystemServerStarted(); } catch (Throwable ex) { Slog.e(\"System\", \"******************************************\"); Slog.e(\"System\", \"************ Failure starting system services\", ex); throw ex; } finally { t.traceEnd(); // StartServices } ...代码省略...} private void startOtherServices(@NonNull TimingsTraceAndSlog t) { t.traceBegin(\"startOtherServices\"); ...代码省略... t.traceBegin(\"StartSystemUI\"); try { startSystemUi(context, windowManagerF);//启动SystemUI } catch (Throwable e) { reportWtf(\"starting System UI\", e); } t.traceEnd(); t.traceEnd(); // startOtherServices } private static void startSystemUi(Context context, WindowManagerService windowManager) { //获取PackageManagerInternal对象实例pm PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); Intent intent = new Intent(); //调用pm的getSystemUiServiceComponent方法获取SystemUIService组件的路径 intent.setComponent(pm.getSystemUiServiceComponent()); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, \"Starting service: \" + intent); //启动SystemUIService服务。 context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted(); }}
  1. SystemServer启动以后,在启动完系统需要的各种服务以后,会调用startSystemUi启动SystemUI。
  2. startSystemUi方法首先获取PackageManagerInternal对象实例pm,然后再调用pm的getSystemUiServiceComponent方法获取SystemUIService组件的路径,最后再调用startServiceAsUser方法启动SystemUIService服务。

1.2 PackageManagerService获取SystemUIService组件路径

//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.javapublic abstract class PackageManagerInternal { /** * @return The SystemUI service component name. */ public abstract ComponentName getSystemUiServiceComponent();}abstract class PackageManagerInternalBase extends PackageManagerInternal { @Override @Deprecated public final ComponentName getSystemUiServiceComponent() { return ComponentName.unflattenFromString(getContext().getResources().getString( com.android.internal.R.string.config_systemUIServiceComponent)); }}public class PackageManagerService implements PackageSender, TestUtilityService {private class PackageManagerInternalImpl extends PackageManagerInternalBase {}}

//frameworks/base/core/res/res/values/config.xml

  <string name=\"config_systemUIServiceComponent\" translatable=\"false\" >com.android.systemui/com.android.systemui.SystemUIService</string>

SystemServer的startSystemUi方法通过PackageManagerService的getSystemUiServiceComponent方法获取到的SystemUI模块的SystemUIService服务组件名,并启动该服务。

二 ActivityThread阶段

2.1 AndroidManifest清单文件

SystemUI模块在源码中的路径为framework/base/package/SystemUI,本质上来说它也是一个APK,拥有更高的权限且常驻内存,由于SystemUI属于APK,自然也有AndroidManifest.xml清单配置文件。

frameworks/base/packages/SystemUI/AndroidManifest.xml

<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:androidprv=\"http://schemas.android.com/apk/prv/res/android\" package=\"com.android.systemui\" android:sharedUserId=\"android.uid.systemui\" xmlns:tools=\"http://schemas.android.com/tools\" coreApp=\"true\"> ...代码省略... <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/android16_patch_adaptive\" 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=\".PhoneSystemUIAppComponentFactory\" android:enableOnBackInvokedCallback=\"true\">...代码省略... <service android:name=\"SystemUIService\"android:exported=\"true\"/>  ...代码省略... </application></manifest>

以上配置信息我们主要关注以下几点:

  • SystemUI的入口为SystemUIApplication。
  • SystemUI是persistent (持久)应用,当应用因为异常而崩溃的时候,系统会重新拉起这个应用。
  • 应用组件工厂属性appComponentFactory指向了PhoneSystemUIAppComponentFactory。
  • SystemUIService服务的声明,且支持外部唤起。

2.2 ActivityThread构建SystemUIApplication实例对象

2.2.1 构建PhoneSystemUIAppComponentFactory对象实例

Android系统在启动一个服务之前,会先检测该服务所对应的进程是否存在,如果不存在则会该创建进程,SystemServer进程在启动SystemUiService服务的时候,同样也需要先检测SystemUIService所对应的进程是否存在;由于是第一次被启动,SystemUI进程自然是不存在的,那么Android系统会先创建SystemUI进程,并进入该进程中代表主线程的ActivityThread类的main方法中,随后会触发ActivityThread比较关键的一个方法handleBindApplication:

//frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal {...代码省略... private void handleBindApplication(AppBindData data) { ...代码省略... //调用LoadedApk的makeApplication方法 Application app = data.info.makeApplication(data.restrictedBackupMode, null); ...代码省略... //调用Instrumentation的callApplicationOnCreate方法,最终会触发Application的onCreate()方法 mInstrumentation.callApplicationOnCreate(app); ...代码省略...  }}//frameworks/base/core/java/android/app/LoadedApk.javapublic final class LoadedApk { public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { //如果已经创建了Application,就直接返回 if (mApplication != null) { return mApplication; } ...代码省略... //创建Application的Context ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //继续调用Instrumentation的newApplication方法创建Application Application app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); ...代码省略... return app; }}//frameworks/base/core/java/android/app/Instrumentation.javapublic class Instrumentation { public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { //调用getFactory方法获取PhoneSystemUIAppComponentFactory对象实例 //并调用其instantiateApplication方法构建SystemUIAppLication对象 Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className); //调用SystemUIAppLication的attach方法 app.attach(context); return app; } private AppComponentFactory getFactory(String pkg) { if (pkg == null) { Log.e(TAG, \"No pkg specified, disabling AppComponentFactory\"); return AppComponentFactory.DEFAULT;//返回AppComponentFactory.DEFAULT } if (mThread == null) { Log.e(TAG, \"Uninitialized ActivityThread, likely app-created Instrumentation,\"  + \" disabling AppComponentFactory\", new Throwable()); return AppComponentFactory.DEFAULT;//返回AppComponentFactory.DEFAULT } LoadedApk apk = mThread.peekPackageInfo(pkg, true); // This is in the case of starting up \"android\". if (apk == null) apk = mThread.getSystemContext().mPackageInfo; //调用LoadedApk的getAppFactory方法 return apk.getAppFactory(); } }public final class LoadedApk { private AppComponentFactory mAppComponentFactory; public AppComponentFactory getAppFactory() { return mAppComponentFactory; } public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage) {...代码省略...//构造方法中调用createAppFactory方法为mAppComponentFactory赋值 mAppComponentFactory = createAppFactory(mApplicationInfo, mBaseClassLoader); } private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) { if (mIncludeCode && appInfo.appComponentFactory != null && cl != null) { try { //ApplicationInfo的appComponentFactory正好对应了前面在AndroidManifest.xml中配置的appComponentFactory属性 return (AppComponentFactory)cl.loadClass(appInfo.appComponentFactory).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { Slog.e(TAG, \"Unable to instantiate appComponentFactory\", e); } } return AppComponentFactory.DEFAULT; } }//frameworks/base/core/java/android/app/AppComponentFactory.javapublic class AppComponentFactory { public static final AppComponentFactory DEFAULT = new AppComponentFactory(); public @NonNull Application instantiateApplication(@NonNull ClassLoader cl, @NonNull String className)  throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Application) cl.loadClass(className).newInstance(); }}
  1. ActivityThread的handleBindApplication方法首先会调用data.info.makeApplication方法获取Application实例对象,对于SystemUI来说,其实就是SystemUIApplication,SystemUIApplication实例对象最终是通过类型为LoadedApk的data.info对象调用makeApplication方法获取的。
  2. Instrumentation的newApplication首先会调用getFactory方法,getFactory方法会判断pkg和类型为ActivityThead的mThread是否为空,如果为空就直接返回AppComponentFactory的DEFAULT属性,如果不为空,getAppFactory会直接返回LoadedApk的属性变量mAppComponentFactory,mAppComponentFactory最早时通过createAppFactory方法进行赋值的,其实就是通过反射将AndroidManifest.xml中appComponentFactory属性所配置的对象实例化,并赋值给mAppComponentFactory。结合前面SystemUI模块的AndroidManifest.xml文件可知,appComponentFactory属性为PhoneSystemUIAppComponentFactory。

2.2.2 构建SystemUIApplication对象实例

public class Instrumentation { public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { //调用getFactory方法获取PhoneSystemUIAppComponentFactory对象实例 //并调用其instantiateApplication方法构建SystemUIAppLication对象 Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className); //调用SystemUIAppLication的attach方法 app.attach(context); return app; }}//frameworks/base/packages/SystemUI/src/com/android/systemui/PhoneSystemUIAppComponentFactory.ktclass PhoneSystemUIAppComponentFactory : SystemUIAppComponentFactoryBase() { override fun createSystemUIInitializer(context: Context) = SystemUIInitializerImpl(context)}//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.ktabstract class SystemUIAppComponentFactoryBase : AppComponentFactory() { override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application { //获取Application的实例对象 val app = super.instantiateApplicationCompat(cl, className) if (app !is ContextInitializer) { throw RuntimeException(\"App must implement ContextInitializer\") } else { //为Application设置回调方法 app.setContextAvailableCallback { context -> //调用createSystemUIInitializerInternal方法 createSystemUIInitializerInternal(context) } } return app }}public class SystemUIApplication extends Application implements SystemUIAppComponentFactory.ContextInitializer { private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback; //SystemUIAppComponentFactoryBase设置回调就是调用的这个方法 @Override public void setContextAvailableCallback(SystemUIAppComponentFactory.ContextAvailableCallback callback) { mContextAvailableCallback = callback; }}
  1. Instrumentation的newApplication方法在调用getFactory获取PhoneSystemUIAppComponentFactory实例对象之后,会调用该对象的instantiateApplicationCompat方法来获取SystemUIApplication实例对象,然后调用SystemUIAppLication的attach方法。

  2. 结合前面的代码可以知道ActivityThread的handleBindApplication方法中,在成功创建SystemUIAppLications实例对象后,会调用调用Instrumentation的callApplicationOnCreate方法,最终会触发Application的onCreate()方法。

2.3 SystemUIApplication触发onContextAvailable回调

ActivityThread的handleBindApplication方法,在成功创建SystemUIAppLications实例对象后,会调用调用Instrumentation的callApplicationOnCreate方法。

public final class ActivityThread extends ClientTransactionHandler {...代码省略... private void handleBindApplication(AppBindData data) { ...代码省略... //获取Application的实例对象 app = data.info.makeApplication(data.restrictedBackupMode, null); ...代码省略... //调用Application的onCreate()方法 mInstrumentation.callApplicationOnCreate(app); ...代码省略... }} public class Instrumentation { public void callApplicationOnCreate(Application app) { //调用Application的onCreate方法 app.onCreate(); }}public class SystemUIApplication extends Application implements SystemUIAppComponentFactory.ContextInitializer { private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback; //SystemUIAppComponentFactoryBase设置回调就是调用的这个方法 @Override public void setContextAvailableCallback(SystemUIAppComponentFactory.ContextAvailableCallback callback) { mContextAvailableCallback = callback; } @Override public void onCreate() { super.onCreate(); ...代码省略... //执行在SystemUIAppComponentFactoryBase类中设置的回调对象的onContextAvailable方法 mInitializer = mContextAvailableCallback.onContextAvailable(this); ...代码省略... }}
  1. 当获取到SystemUIApplication的实例之后,会继续调用Instrumentation的callApplicationOnCreate方法,callApplicationOnCreate方法会触发SystemUIApplication的onCreate方法。
  2. SystemUIApplication的onCreate会调用回调对象mContextAvailableCallback的onContextAvailable方法。

三、PhoneSystemUIAppComponentFactory创建SystemUI模块的Dagger2组件

3.1 SystemUIInitializer的init方法

在2.2.2节我们有提到SystemUIAppComponentFactoryBase为SystemUIApplication设置回调方法所对应的关键代码:

abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() { override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application { //获取Application的实例对象 val app = super.instantiateApplicationCompat(cl, className) if (app !is ContextInitializer) { throw RuntimeException(\"App must implement ContextInitializer\") } else { //为Application设置回调方法 app.setContextAvailableCallback { context -> //调用createSystemUIInitializerInternal方法 createSystemUIInitializerInternal(context) } } return app } protected abstract fun createSystemUIInitializer(context: Context): SystemUIInitializer private fun createSystemUIInitializerInternal(context: Context): SystemUIInitializer { return systemUIInitializer ?: run { val initializer = createSystemUIInitializer(context.applicationContext) try { //调用SystemUIInitializer的init方法 initializer.init(false) } catch (exception: ExecutionException) { throw RuntimeException(\"Failed to initialize SysUI\", exception) } catch (exception: InterruptedException) { throw RuntimeException(\"Failed to initialize SysUI\", exception) } //对SysUIComponent组件进行依赖注入 initializer.sysUIComponent.inject( this@SystemUIAppComponentFactoryBase ) systemUIInitializer = initializer return initializer } }}class PhoneSystemUIAppComponentFactory : SystemUIAppComponentFactoryBase() { override fun createSystemUIInitializer(context: Context) = SystemUIInitializerImpl(context)//构建SystemUIInitializerImpl对象}//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.ktclass SystemUIInitializerImpl(context: Context) : SystemUIInitializer(context) { override fun getGlobalRootComponentBuilder(): GlobalRootComponent.Builder { return DaggerReferenceGlobalRootComponent.builder()//构建本地根组件,dagger自动产生的类,依赖于ReferenceGlobalRootComponent }}//frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/ReferenceGlobalRootComponent.java@Singleton@Component(modules = {GlobalModule.class})public interface ReferenceGlobalRootComponent extends GlobalRootComponent { /** * Builder for a ReferenceGlobalRootComponent. */ @Component.Builder interface Builder extends GlobalRootComponent.Builder { ReferenceGlobalRootComponent build(); } /** * Builder for a {@link ReferenceSysUIComponent}, which makes it a subcomponent of this class. */ ReferenceSysUIComponent.Builder getSysUIComponent();}//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.javapublic abstract class SystemUIInitializer { private static final String TAG = \"SystemUIFactory\"; private final Context mContext; private GlobalRootComponent mRootComponent;//SystemUI应用的Dagger2根组件 private WMComponent mWMComponent;//和WindowManager有关的Dagger2子组件 private SysUIComponent mSysUIComponent;//和SystemUI核心组件有关的Dagger2子组件 private InitializationChecker mInitializationChecker;//是否对组件进行初始化 public SystemUIInitializer(Context context) { mContext = context; } //初始化SystemUI模块的所有Dagger2组件 public void init(boolean fromTest) throws ExecutionException, InterruptedException { //构建本地组件,由于SystemUIInitializerImpl重新了这个方法,这里返回的其实是ReferenceGlobalRootComponent对象 mRootComponent = getGlobalRootComponentBuilder() .context(mContext) .instrumentationTest(fromTest) .build(); mInitializationChecker = mRootComponent.getInitializationChecker(); //如果不是为了进行测试、且应用属于System用户组、进程名和com.andorid.systemui相等才返回true boolean initializeComponents = mInitializationChecker.initializeComponents(); //构建和WMShell相关的组件 setupWmComponent(mContext); //这里得到的其实是ReferenceSysUIComponent.Builder对象 SysUIComponent.Builder builder = mRootComponent.getSysUIComponent(); if (initializeComponents) { // Only initialize when not starting from tests since this currently initializes some // components that shouldn\'t be run in the test environment builder = prepareSysUIComponentBuilder(builder, mWMComponent)  .setShell(mWMComponent.getShell())  .setPip(mWMComponent.getPip())  .setSplitScreen(mWMComponent.getSplitScreen())  .setOneHanded(mWMComponent.getOneHanded())  .setBubbles(mWMComponent.getBubbles())  .setTaskViewFactory(mWMComponent.getTaskViewFactory())  .setShellTransitions(mWMComponent.getShellTransitions())  .setKeyguardTransitions(mWMComponent.getKeyguardTransitions())  .setStartingSurface(mWMComponent.getStartingSurface())  .setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())  .setRecentTasks(mWMComponent.getRecentTasks())  .setBackAnimation(mWMComponent.getBackAnimation())  .setDesktopMode(mWMComponent.getDesktopMode())  .setAppZoomOut(mWMComponent.getAppZoomOut()); // Only initialize when not starting from tests since this currently initializes some // components that shouldn\'t be run in the test environment mWMComponent.init(); } else { // TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option // is separating this logic into newly creating SystemUITestsFactory. builder = prepareSysUIComponentBuilder(builder, mWMComponent)  .setShell(new ShellInterface() {})  .setPip(Optional.ofNullable(null))  .setSplitScreen(Optional.ofNullable(null))  .setOneHanded(Optional.ofNullable(null))  .setBubbles(Optional.ofNullable(null))  .setTaskViewFactory(Optional.ofNullable(null))  .setShellTransitions(new ShellTransitions() {})  .setKeyguardTransitions(new KeyguardTransitions() {})  .setDisplayAreaHelper(Optional.ofNullable(null))  .setStartingSurface(Optional.ofNullable(null))  .setRecentTasks(Optional.ofNullable(null))  .setBackAnimation(Optional.ofNullable(null))  .setDesktopMode(Optional.ofNullable(null))  .setAppZoomOut(Optional.ofNullable(null)); } //得到ReferenceSysUIComponent组件 mSysUIComponent = builder.build(); // Every other part of our codebase currently relies on Dependency, so we // really need to ensure the Dependency gets initialized early on. //创建Dependency实例,不同组件之间沟通的桥梁 Dependency dependency = mSysUIComponent.createDependency(); //初始化Dependency dependency.start(); }}
  1. SystemUIApplication的onCreate会调用回调对象mContextAvailableCallback的onContextAvailable方法,回调到SystemUIAppComponentFactoryBase类的createSystemUIInitializerInternal方法。
  2. createSystemUIInitializerInternal方法先是触发SystemUIInitializer的init方法,由于SystemUIInitializerImpl重写了getGlobalRootComponentBuilder方法,所以调用getGlobalRootComponentBuilder方法得到的结果就是mRootComponent变成了ReferenceGlobalRootComponent实例对象。
  3. 紧接着构建WMShell相关的组件mWMComponent、与SystemUI相关的组件mSysUIComponent,并对这两个组件初始化,最后还会创建Dependency实例对象并进行初始化,Dependency是SystemUI模块不同组件之间沟通的桥梁。
  4. 调用ReferenceSysUIComponent.Builder的build方法,得到ReferenceSysUIComponent组件,会调用createDependency方法创建对应的Dependency对象实例,调用该对象的inject方法进行依赖注入。

3.2 ReferenceSysUIComponent

对于PhoneSystemUIAppComponentFactory来说,其对应的SystemUI组件实例都是通过ReferenceSysUIComponent得到的,所以我们要具体看下这个类。

//frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java@SysUISingleton@Subcomponent(modules = { DefaultComponentBinder.class, DependencyProvider.class, NotificationInsetsModule.class, QsFrameTranslateModule.class, SystemUIModule.class, SystemUICoreStartableModule.class, SysUIUnfoldModule.class, ReferenceSystemUIModule.class})public interface ReferenceSysUIComponent extends SysUIComponent { /** * Builder for a ReferenceSysUIComponent. */ @SysUISingleton @Subcomponent.Builder interface Builder extends SysUIComponent.Builder { ReferenceSysUIComponent build(); } /** * Member injection into the supplied argument. */ void inject(CustomizationProvider customizationProvider);}//frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java@SysUISingleton//单例@Subcomponent(//子组件modules = {//当前连接组件用到的Module(Module会提供我们需要的各种对象实例) DefaultComponentBinder.class, DependencyProvider.class, NotificationInsetsModule.class, QsFrameTranslateModule.class, SystemUIModule.class, SystemUICoreStartableModule.class, ReferenceSystemUIModule.class})public interface SysUIComponent { /** * Builder for a SysUIComponent. */ @SysUISingleton @Subcomponent.Builder interface Builder {...代码省略... SysUIComponent build(); }...代码省略... /** * Returns {@link CoreStartable}s that should be started with the application. */ Map<Class<?>, Provider<CoreStartable>> getStartables(); /** * Returns {@link CoreStartable}s that should be started for every user. */ @PerUser Map<Class<?>, Provider<CoreStartable>> getPerUserStartables(); /** * Returns {@link CoreStartable} dependencies if there are any. */ @Dependencies Map<Class<?>, Set<Class<? extends CoreStartable>>> getStartableDependencies(); /** * Member injection into the supplied argument. */ void inject(SystemUIAppComponentFactoryBase factory);}

3.3 SystemUI组件依赖注入

SystemUIAppComponentFactoryBase类的createSystemUIInitializerInternal方法在调用完init方法之后,会得到SystemUIInitializerImpl对象,对应的initializer.mSysUIComponent其实是ReferenceSysUIComponent对象,调用该对象的inject方法进行依赖注入。

//base/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java@Module(includes = { AccessibilityModule.class, AccessibilityRepositoryModule.class, AospPolicyModule.class, BatterySaverModule.class, BrightnessSliderModule.class, CentralSurfacesModule.class, ClipboardOverlayOverrideModule.class, CollapsedStatusBarFragmentStartableModule.class, ConnectingDisplayViewModel.StartableModule.class, DefaultBlueprintModule.class, DeviceStateAutoRotateModule.class, EmergencyGestureModule.class, GestureModule.class, HeadsUpModule.class, KeyguardModule.class, KeyboardShortcutsModule.class, KeyguardBlueprintModule.class, KeyguardSectionsModule.class, KeyboardTouchpadTutorialModule.class, MediaModule.class, MediaMuteAwaitConnectionCli.StartableModule.class, MultiUserUtilsModule.class, NavigationBarControllerModule.class, NearbyMediaDevicesManager.StartableModule.class, PowerModule.class, QSModule.class, RearDisplayModule.class, RecentsModule.class, ReferenceNotificationsModule.class, NoopPosturingModule.class, ReferenceScreenshotModule.class, RotationLockModule.class, RotationLockNewModule.class, ScreenDecorationsModule.class, StatusBarPhoneModule.class,//手机状态栏 SystemActionsModule.class, ShadeModule.class, SqueezeEffectRepositoryModule.class, StartCentralSurfacesModule.class, SceneContainerFrameworkModule.class, SysUICoroutinesModule.class, SysUIUnfoldStartableModule.class, UnfoldTransitionModule.Startables.class, ToastModule.class, TopLevelWindowEffectsModule.class, TouchpadTutorialModule.class, VolumeModule.class,//音量调控VolumeUI WallpaperModule.class, ShortcutHelperModule.class, ContextualEducationModule.class,})public abstract class ReferenceSystemUIModule {...代码省略...}//framework/base/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.javapublic interface VolumeModule { /** Starts VolumeUI. */ @Binds @IntoMap @ClassKey(VolumeUI.class) CoreStartable bindVolumeUIStartable(VolumeUI impl);}//framework/base/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java@SysUISingletonpublic class VolumeUI implements CoreStartable, ConfigurationController.ConfigurationListener { @Inject public VolumeUI(Context context, VolumeDialogComponent volumeDialogComponent, AudioRepository audioRepository, AudioSharingInteractor audioSharingInteractor, JavaAdapter javaAdapter, VolumeLogger volumeLogger) {...代码省略... } @Override public void start() {...代码省略... }}

其类上面的注解类相关的对象,像是StatusBarPhoneModule、VolumeModule、VolumeUI等类的对象实例后续在被调用的时候,都可以直接通过注解配置的方式让Dagger2框架会帮创建对应的对象实例。

3.4 ContextComponentHelper

SysUIComponent的inject(SystemUIAppComponentFactoryBase factory)方法被执行之后,SystemUIAppComponentFactoryBase类中有被@Inject注解标记的属性变量都会被赋值。事实上SystemUIAppComponentFactoryBase类中只有一个被@Inject注解标记的属性变量componentHelper:

abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() { companion object { private const val TAG = \"AppComponentFacreateSystemUIInitializerctory\" // Must be static due to http://b/141008541. var systemUIInitializer: SystemUIInitializer? = null } @set:Inject lateinit var componentHelper: ContextComponentHelper//Dagger2依赖注入会对这个对象进行赋值}

在执行完inject方法之后,类型为ContextComponentHelper的componentHelper属性也会被赋值。

//frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.javapublic interface ContextComponentHelper { /** Turns a classname into an instance of the class or returns null. */ Activity resolveActivity(String className); /** Turns a classname into an instance of the class or returns null. */ RecentsImplementation resolveRecents(String className); /** Turns a classname into an instance of the class or returns null. */ Service resolveService(String className); /** Turns a classname into an instance of the class or returns null. */ BroadcastReceiver resolveBroadcastReceiver(String className);}

ContextComponentHelper 接口提供了4个方法,分别通过类名返回Activity、RecentsImplementation、Service、BroadcastReceiver类型的实例对象。该接口目前只有一个实现类ContextComponentResolver。

//frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java//在SystemUI模块通过dagger依赖注入的这个对象为单例@SysUISingletonpublic class ContextComponentResolver implements ContextComponentHelper { private final Map<Class<?>, Provider<Activity>> mActivityCreators; private final Map<Class<?>, Provider<Service>> mServiceCreators; private final Map<Class<?>, Provider<RecentsImplementation>> mRecentsCreators; private final Map<Class<?>, Provider<BroadcastReceiver>> mBroadcastReceiverCreators; @Inject ContextComponentResolver(Map<Class<?>, Provider<Activity>> activityCreators, Map<Class<?>, Provider<Service>> serviceCreators, Map<Class<?>, Provider<RecentsImplementation>> recentsCreators, Map<Class<?>, Provider<BroadcastReceiver>> broadcastReceiverCreators) { mActivityCreators = activityCreators; mServiceCreators = serviceCreators; mRecentsCreators = recentsCreators; mBroadcastReceiverCreators = broadcastReceiverCreators; } /** * Looks up the Activity class name to see if Dagger has an instance of it. */ @Override public Activity resolveActivity(String className) { return resolve(className, mActivityCreators); } /** * Looks up the BroadcastReceiver class name to see if Dagger has an instance of it. */ @Override public BroadcastReceiver resolveBroadcastReceiver(String className) { return resolve(className, mBroadcastReceiverCreators); } /** * Looks up the RecentsImplementation class name to see if Dagger has an instance of it. */ @Override public RecentsImplementation resolveRecents(String className) { return resolve(className, mRecentsCreators); } /** * Looks up the Service class name to see if Dagger has an instance of it. */ @Override public Service resolveService(String className) { return resolve(className, mServiceCreators); } private <T> T resolve(String className, Map<Class<?>, Provider<T>> creators) { try { Class<?> clazz = Class.forName(className); Provider<T> provider = creators.get(clazz); return provider == null ? null : provider.get(); } catch (ClassNotFoundException e) { return null; } }}

由于ContextComponentResolver的构造方法添加了@Inject注解,这样mActivityCreators、mServiceCreators、mRecentsCreators、mBroadcastReceiverCreators都会被实例化,后续其他类可以通过调用此类的resolveActivity、resolveBroadcastReceiver、resolveRecents、resolveService、这4个方法获取className对应的Activity、BroadcastReceiver、RecentsImplementation、Service实例对象。

3.5 时序图

Android 16系统源码_SystemUI(一)SystemUI的启动流程_com.android.systemui
SystemServer在启动SystemUIService服务之前,由于检测到该服务所对应的进程不存在,于是便创建了该进程和该进程所对应的SystemUIApplication,执行SystemUIApplication的onCreate方法,并执行SystemUIAppComponentFactoryBase所设置的回调方法,在回调方法中调用SystemUIInitializer的init方法创建了SystemUI模块的所有Dagger2组件。

四、在 SystemUIService启动SystemUI模块所需的所有组件。

4.1 SystemUIApplication的onCreate方法

public class SystemUIApplication extends Application implements SystemUIAppComponentFactory.ContextInitializer { private BootCompleteCacheImpl mBootCompleteCache; private boolean mServicesStarted;//服务是否已经被启动 private SystemUIAppComponentFactoryBase.ContextAvailableCallback mContextAvailableCallback;//回调方法 private SysUIComponent mSysUIComponent;//SystemUI子组件 private SystemUIInitializer mInitializer; private ProcessWrapper mProcessWrapper; public SystemUIApplication() { super(); if (!isSubprocess()) { Trace.registerWithPerfetto(); } Log.v(TAG, \"SystemUIApplication constructed.\"); // SysUI may be building without protolog preprocessing in some cases ProtoLog.REQUIRE_PROTOLOGTOOL = false; } @Override public void onCreate() { super.onCreate(); Log.v(TAG, \"SystemUIApplication created.\"); ...代码省略... //执行在SystemUIAppComponentFactoryBase类中设置的回调 mInitializer = mContextAvailableCallback.onContextAvailable(this); ...代码省略... mProcessWrapper = rootComponent.getProcessWrapper(); if (mProcessWrapper.isSystemUser()) {  ...代码省略... 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++) { //调用notifyBootCompleted方法 notifyBootCompleted(mServices[i]); }  } } }, bootCompletedFilter);  ...代码省略... } else { // We don\'t need to startServices for sub-process that is doing some tasks. // (screenshots, sweetsweetdesserts or tuner ..) if (isSubprocess()) { 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. startSecondaryUserServicesIfNeeded(); } } private static void notifyBootCompleted(CoreStartable coreStartable) { if (Trace.isEnabled()) { Trace.traceBegin(  Trace.TRACE_TAG_APP,  coreStartable.getClass().getSimpleName() + \".onBootCompleted()\"); } coreStartable.onBootCompleted(); Trace.endSection(); }}

SystemUIApplication的onCreate方法会做一些初始化操作,然后会因为一个条件判断,而出现两个分支。
1)如果当前用户是SYSTEM用户,会进入到if这个分支中,注册监听 boot completed 的通知,最后完全启动后就会回调各个组件onBootCompleted。
2)如果当前用户不是SYSTEM用户,例如多用户登录使用的情况,这时候系统其实已经启动过了,就会走 else 的分支进入到 startSecondaryUserServicesIfNeeded()用于启动 SystemUI 所需的服务组件,这个分支是根据用户来启动相应的服务的。

4.2 SystemServer的onCreate方法

前面讲了这么多,SystemServer终于等到SystemUIApplication的onCreate方法执行完毕了,这个时候系统才会真正启动SystemUIService这个服务,SystemUIService被启动之后会立刻执行onCreate方法:

//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.javapublic class SystemUIService extends Service { @Override public void onCreate() { super.onCreate(); // 启动属于System用户的SystemUI组件 ((SystemUIApplication) getApplication()).startSystemUserServicesIfNeeded(); ...代码省略... }}

SystemUIService的onCreate方法会重新获取SystemUIApplication实例对象,并调用该对象的startServicesIfNeeded方法。

4.3 SystemUIApplication的startSystemUserServicesIfNeeded方法

public class SystemUIApplication extends Application implements SystemUIAppComponentFactory.ContextInitializer { private CoreStartable[] mServices;//SystemUI组件数组 private SysUIComponent mSysUIComponent; @Override public void onCreate() { super.onCreate(); Log.v(TAG, \"SystemUIApplication created.\"); //得到ReferenceSysUIComponent对象实例 mInitializer = mContextAvailableCallback.onContextAvailable(this); ...代码省略... } public void startSystemUserServicesIfNeeded() { if (!shouldStartSystemUserServices()) { Log.wtf(TAG, \"Tried starting SystemUser services on non-SystemUser\"); return; // Per-user startables are handled in #startSystemUserServicesIfNeeded. } final String vendorComponent = mInitializer.getVendorComponent(getResources()); Map<Class<?>, Provider<CoreStartable>> sortedStartables = new TreeMap<>( Comparator.comparing(Class::getName)); //调用ReferenceSysUIComponent的getStartables方法和getPerUserStartables方法,获取当前存在的SystemUI组件对象 sortedStartables.putAll(mSysUIComponent.getStartables()); sortedStartables.putAll(mSysUIComponent.getPerUserStartables()); startServicesIfNeeded(sortedStartables, \"StartServices\", vendorComponent); } private void startServicesIfNeeded( Map<Class<?>, Provider<CoreStartable>> startables, String metricsPrefix, String vendorComponent) { if (mServicesStarted) { return; } mServices = new CoreStartable[startables.size() + (vendorComponent == null ? 0 : 1)]; ...代码省略... boolean startedAny = false; ArrayDeque<Map.Entry<Class<?>, Provider<CoreStartable>>> queue; ArrayDeque<Map.Entry<Class<?>, Provider<CoreStartable>>> nextQueue = new ArrayDeque<>(startables.entrySet()); int numIterations = 0; int serviceIndex = 0; do { startedAny = false; queue = nextQueue; nextQueue = new ArrayDeque<>(startables.size()); while (!queue.isEmpty()) { Map.Entry<Class<?>, Provider<CoreStartable>> entry = queue.removeFirst(); Class<?> cls = entry.getKey(); Set<Class<? extends CoreStartable>> deps = mSysUIComponent.getStartableDependencies().get(cls); if (deps == null || startedStartables.containsAll(deps)) {  String clsName = cls.getName();  int i = serviceIndex; // Copied to make lambda happy.  timeInitialization( clsName, () -> mServices[i] = startStartable(clsName, entry.getValue()),//触发SystemUI组件的start方法 log, metricsPrefix);  startedStartables.add(cls);  startedAny = true;  serviceIndex++; } else {  nextQueue.add(entry); } } numIterations++; } while (startedAny && !nextQueue.isEmpty()); // if none were started, stop. } private static CoreStartable startStartable(CoreStartable startable) { //触发SystemUI组件的start方法 startable.start(); return startable; }}//base/packages/SystemUI/src/com/android/systemui/CoreStartable.javapublic interface CoreStartable extends Dumpable { void start(); default void onBootCompleted() { }}//base/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java@Module(includes = { VolumeModule.class,})public abstract class ReferenceSystemUIModule {...代码省略...}//framework/base/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.javapublic interface VolumeModule { /** Starts VolumeUI. */ @Binds @IntoMap @ClassKey(VolumeUI.class) CoreStartable bindVolumeUIStartable(VolumeUI impl);}//framework/base/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java@SysUISingletonpublic class VolumeUI implements CoreStartable, ConfigurationController.ConfigurationListener { @Inject public VolumeUI(Context context, VolumeDialogComponent volumeDialogComponent, AudioRepository audioRepository, AudioSharingInteractor audioSharingInteractor, JavaAdapter javaAdapter, VolumeLogger volumeLogger) {...代码省略... } @Override public void start() {...代码省略... }}
  1. SystemUIApplication的onCreate方法先是为mInitializer赋值,结合前面的代码可以知道默认这里的类型是ReferenceSysUIComponent
  2. SystemUIApplication的startSystemUserServicesIfNeeded方法分别调用ReferenceSysUIComponent的getStartables和getPerUserStartables方法,得到对应的实现了CoreStartable接口的实例对象,并将其存储到类型为CoreStartable的mServices数组中。
  3. Android16中的SystemUI组件都只是普通的Java类,和之前的系统版本有所不同,现在因为没有SystemUI这个抽象父类了,自然也不需要组件来继承,但是所有的SystemUI组件都有实现CoreStartable 这个接口。
  4. SystemUIApplication的startServicesIfNeeded方法会遍历mServices数组中的每个对象,并调用该对象的start() 方法,之后还会调用该类的onBootCompleted( ) 方法。
  5. 不同功能的SystemUI组件会在start方法中构建自己所需要的UI交互和业务逻辑。

4.4 时序图

Android 16系统源码_SystemUI(一)SystemUI的启动流程_com.android.systemui

1、Android 系统在启动之后,首先会Zygote进程,Zygote进程又会进一步启动 SystemServer进程,它会启动各种系统所需要的服务,在监听AMS启动完毕之后,还会启动SystemUIService。

2、在启动SystemUIService服务之前,系统首先会创建SystemUI对应的进程,构建PhoneSystemUIAppComponentFactory实例对象,调用其instantiateApplicationCompat方法创建SystemUIApplication实例对象并设置回调方法。

3、执行SystemUIApplication的onCreate方法,执行PhoneSystemUIAppComponentFactory所设置的回调方法,调用SystemUIAppComponentFactoryBase的createSystemUIInitializerInternal方法,该方法又调用SystemUIInitializerImpl对象的init方法创建SystemUI模块所需的Dagger2组件并初始化。

4、启动SystemUIService服务,执行该服务的onCreate方法,在该服务的onCreate方法中会再次调用SystemUIApplication的startSystemUserServicesIfNeeded方法,该方法会变遍历当前存放在mServices中的SystemUI组件,执行组件的start方法和onBootCompleted方法,不同功能的SystemUI组件会在自己的start方法中构建自己所需要的UI和业务逻辑。

💡 技术无价,赞赏随心

写文不易,如果本文帮你避开了“八小时踩坑”,或者让你直呼“学到了!”
欢迎扫码赞赏,让我知道这篇内容值得!