前言
Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Navigation Bar,下拉通知栏,下拉快捷栏,音量调控UI,电源调控UI,近期任务界面 Recent Task 等等。
在 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.java
public 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();
}
}
- SystemServer启动以后,在启动完系统需要的各种服务以后,会调用startSystemUi启动SystemUI。
- startSystemUi方法首先获取PackageManagerInternal对象实例pm,然后再调用pm的getSystemUiServiceComponent方法获取SystemUIService组件的路径,最后再调用startServiceAsUser方法启动SystemUIService服务。
1.2 PackageManagerService获取SystemUIService组件路径
//frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public 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
<!-- SystemUi service component -->
<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.java
public 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.java
public 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.java
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;
}
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.java
public 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();
}
}
- ActivityThread的handleBindApplication方法首先会调用data.info.makeApplication方法获取Application实例对象,对于SystemUI来说,其实就是SystemUIApplication,SystemUIApplication实例对象最终是通过类型为LoadedApk的data.info对象调用makeApplication方法获取的。
- 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.kt
class PhoneSystemUIAppComponentFactory : SystemUIAppComponentFactoryBase() {
override fun createSystemUIInitializer(context: Context) = SystemUIInitializerImpl(context)
}
//frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
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
}
}
public class SystemUIApplication extends Application implements
SystemUIAppComponentFactory.ContextInitializer {
private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
//SystemUIAppComponentFactoryBase设置回调就是调用的这个方法
@Override
public void setContextAvailableCallback(SystemUIAppComponentFactory.ContextAvailableCallback callback) {
mContextAvailableCallback = callback;
}
}
-
Instrumentation的newApplication方法在调用getFactory获取PhoneSystemUIAppComponentFactory实例对象之后,会调用该对象的instantiateApplicationCompat方法来获取SystemUIApplication实例对象,然后调用SystemUIAppLication的attach方法。
-
结合前面的代码可以知道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);
...代码省略...
}
}
- 当获取到SystemUIApplication的实例之后,会继续调用Instrumentation的callApplicationOnCreate方法,callApplicationOnCreate方法会触发SystemUIApplication的onCreate方法。
- 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.kt
class 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.java
public 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();
}
}
- SystemUIApplication的onCreate会调用回调对象mContextAvailableCallback的onContextAvailable方法,回调到SystemUIAppComponentFactoryBase类的createSystemUIInitializerInternal方法。
- createSystemUIInitializerInternal方法先是触发SystemUIInitializer的init方法,由于SystemUIInitializerImpl重写了getGlobalRootComponentBuilder方法,所以调用getGlobalRootComponentBuilder方法得到的结果就是mRootComponent变成了ReferenceGlobalRootComponent实例对象。
- 紧接着构建WMShell相关的组件mWMComponent、与SystemUI相关的组件mSysUIComponent,并对这两个组件初始化,最后还会创建Dependency实例对象并进行初始化,Dependency是SystemUI模块不同组件之间沟通的桥梁。
- 调用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.java
public interface VolumeModule {
/** Starts VolumeUI. */
@Binds
@IntoMap
@ClassKey(VolumeUI.class)
CoreStartable bindVolumeUIStartable(VolumeUI impl);
}
//framework/base/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@SysUISingleton
public 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.java
public 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依赖注入的这个对象为单例
@SysUISingleton
public 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 时序图
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.java
public 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.java
public 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.java
public interface VolumeModule {
/** Starts VolumeUI. */
@Binds
@IntoMap
@ClassKey(VolumeUI.class)
CoreStartable bindVolumeUIStartable(VolumeUI impl);
}
//framework/base/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@SysUISingleton
public 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() {
...代码省略...
}
}
- SystemUIApplication的onCreate方法先是为mInitializer赋值,结合前面的代码可以知道默认这里的类型是ReferenceSysUIComponent
- SystemUIApplication的startSystemUserServicesIfNeeded方法分别调用ReferenceSysUIComponent的getStartables和getPerUserStartables方法,得到对应的实现了CoreStartable接口的实例对象,并将其存储到类型为CoreStartable的mServices数组中。
- Android16中的SystemUI组件都只是普通的Java类,和之前的系统版本有所不同,现在因为没有SystemUI这个抽象父类了,自然也不需要组件来继承,但是所有的SystemUI组件都有实现CoreStartable 这个接口。
- SystemUIApplication的startServicesIfNeeded方法会遍历mServices数组中的每个对象,并调用该对象的start() 方法,之后还会调用该类的onBootCompleted( ) 方法。
- 不同功能的SystemUI组件会在start方法中构建自己所需要的UI交互和业务逻辑。
4.4 时序图
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和业务逻辑。
💡 技术无价,赞赏随心
写文不易,如果本文帮你避开了“八小时踩坑”,或者让你直呼“学到了!”
欢迎扫码赞赏,让我知道这篇内容值得!