Android11 SystemUI解析
在上篇文章Android11 最近任务Recents功能分析过程中,针对SystemUI内部功能逻辑变化,发现在进程启动过程中有新的变化,比如AppComponentFactory的引入,在Android系统中,有些核心应用需要开机就启动,就像SystemUI;
SystemUI进程是Android系统中一个核心进程,StatusBar和NavigationBar等逻辑都是来SystemUI进程里面处理的,本文针对Android11版本对SystemUI启动过程进行分析:
一.启动入口
Android系统在启动时,会启动system_server进程,接着会调用到SystemServer.java中的main()方法,简单回忆一下:
public static void main(String[] args) {
new SystemServer().run();
}
接下来会调用到run()方法:
private void run() {
;;;;;;;;;;;;;;;;;;;;;;;;;;;
// Start services.
try {
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
在run()内部会start services(),包括启动一些核心的服务包括AMS、WMS、PMS等,在startOtherServices()里面会调用到startSystemUi(),看一下该方法的具体实现:
private static void startSystemUi(Context context, WindowManagerService windowManager) {
PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
Intent intent = new Intent();
intent.setComponent(pm.getSystemUiServiceComponent());
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
可以看到,在startSystemUi()内部启动了一个service,该service对应的详细参数是通过getSystemUiServiceComponent()来获取的,该方法具体实现是在PackageManagerService.java里面:
@Override
public ComponentName getSystemUiServiceComponent() {
return ComponentName.unflattenFromString(mContext.getResources().getString(
com.android.internal.R.string.config_systemUIServiceComponent));
}
<!-- SystemUi service component -->
<string name="config_systemUIServiceComponent" translatable="false"
>com.android.systemui/com.android.systemui.SystemUIService</string>
可以看到,getSystemUiServiceComponent()获取的ComponentName对应的service Intent是SystemUIService,即启动了SystemUIService;
通过以上可以看到:在system_server进程启动后,会调用startServiceAsUser()来启动SystemUIService,即启动了SystemUI进程。
二.进程启动
前面分析了是通过startService()来启动进程,关于startService()是如何启动进程的,startService()跟bindService()启动方式是类似的,可以参考之前分析过的文章Android 进程通信bindService详解,本文直接从ActivityThread来进行分析:
1.ActivityThread.java
在进行启动时,会调用到main()方法,然后通过attachApplication()与AMS进行一系列交互后,会调用到handBindApplication()方法:
private void handleBindApplication(AppBindData data) {
;;;;;;;;;;;;;;;;;;;;;;;;
Application app;
app = data.info.makeApplication(data.restrictedBackupMode, null);
;;;;;;;;;;;;;;;;;;;;
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
}
}
data.info对应的是LoadedApk,通过LoadedApk的makeApplication()来创建Application实例,然后通过Instrumentation的callApplicationOnCreate(app)来回调Application的onCreate()方法,先看一下makeApplication()方法:
2.LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
;;;;;;;;;;;;;;
Application app = null;
String appClass = mApplicationInfo.className;
try {
;;;;;;;;;;;;;;;;;;;;;;;;;
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
}
;;;;;;;;;;;;;;;;;;;;;;;;;;
return app;
}
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo compatInfo, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode, boolean registerPackage) {
mActivityThread = activityThread;
;;;;;;;;;;;;;;;;;;;;;;
mAppComponentFactory = createAppFactory(mApplicationInfo, mBaseClassLoader);
}
可以看到,makeApplication()内部还是通过Instrucmentation的newApplication()来创建的Application实例,看一下Instrucmentation内部的实现:
3.Instrumentation.java
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;
}
可以看到,在newApplication()内部获取Application实例经过了两步操作:
1.先执行getFactory()获取AppComponentFactory实例;
2.执行instantiateApplication()来获取Application实例;
对比Android8.1发现,Android8.1直接调用Application app = (Application)clazz.newInstance(),接下来先看一下getFactory()实现:
private AppComponentFactory getFactory(String pkg) {
;;;;;;;;;;;;;;;;;;;;;;;;;
LoadedApk apk = mThread.peekPackageInfo(pkg, true);
;;;;;;;;;;;;;;;;;;;;
return apk.getAppFactory();
}
可以看到,getFactory()是通过LoadedApk来获取,根据调用关系看一下对应实现:
//LoadedApk.java
private AppComponentFactory mAppComponentFactory;
public AppComponentFactory getAppFactory() {
return mAppComponentFactory;
}
getAppFactory()返回的是AppComponentFactory实例,该实例是在LoadedApk的构造方法内部就执行了createAppFactory()进行创建,关于AppComponentFactory,后面再进行分析,先看一下createAppFactory():
//LoadedApk.java
private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
if (mIncludeCode && appInfo.appComponentFactory != null && cl != null) {
try {
return (AppComponentFactory)
cl.loadClass(appInfo.appComponentFactory).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
}
}
return AppComponentFactory.DEFAULT;
}
在方法内部会先进行判断,mIncludeCode是true,classloader不为null,最后决定条件就是appInfo.appComponentFactory是否为null,如果不为null,则会通过ClassLoader去加载对应的类进行创建实例,如果为null,则直接返回AppComponentFactory DEFAULT实例;接下来需要知道的有两点:
1.AppComponentFactory是什么?
2.appInfo.appComponentFactory获取的什么内容?
4.AppComponentFactory.java
/**
* Interface used to control the instantiation of manifest elements.
*
* @see #instantiateApplication
* @see #instantiateActivity
* @see #instantiateClassLoader
* @see #instantiateService
* @see #instantiateReceiver
* @see #instantiateProvider
*/
public class AppComponentFactory {
/**
* Allows application to override the creation of the application object. This can be used to
* perform things such as dependency injection or class loader changes to these
* classes.
* <p>
* This method is only intended to provide a hook for instantiation. It does not provide
* earlier access to the Application object. The returned object will not be initialized
* as a Context yet and should not be used to interact with other android APIs.
*
* @param cl The default classloader to use for instantiation.
* @param className The class to be instantiated.
*/
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
@NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Application) cl.loadClass(className).newInstance();
}
;;;;;;;;;;;;;;;;;;;;;;
}
通过类注释可以看到:用来控制清单文件元素实例话的接口;
本文只看instantiateApplication(),方法注释:允许应用程序重写应用程序对象的创建,可以用来对这些类执行依赖项注入或类装入器更改等操作;此方法仅用于提供用于实例化的hook。它不提供对应用程序对象的早期访问。返回的对象尚未初始化为上下文,不应用于与其他android API交互;instantiateApplication()最终返回的是Application实例;
简单总结一下:允许应用内部创建AppComponentFactory的实现类,重写instantiateApplication()在内部做一下inject工作,由于在实例化时还未attach(context),所以不能执行上下文操作等交互逻辑;
接下来就是看SystemUI内部的具体实现,appComponentFactory是如何在AndroidManifest.xml中使用的?是如何实现的AppComponentFactory类?
三.具体实现
先看一下SystemUI的AndroidManifest.xml文件:
1.AndroidManifest.xml
<application
android:name=".SystemUIApplication"
android:persistent="true"
;;;;;;;;;;;;;;;;;;;;
android:appComponentFactory=".SystemUIAppComponentFactory">
<service android:name="SystemUIService"android:exported="true"/>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
可以看到,在application标签下加入了 android:appComponentFactory=".SystemUIAppComponentFactory",PMS会将android:appComponentFactory解析到appInfo.appComponentFactory,所以前面在newApplication()内部getFactory()返回的是SystemUIAppComponentFactory实例,一起看一下SystemUIAppComponentFactory的具体实现:
2.SystemUIAppComponentFactory.java
import androidx.core.app.AppComponentFactory;
public class SystemUIAppComponentFactory extends AppComponentFactory {
@Inject
public ContextComponentHelper mComponentHelper;
public SystemUIAppComponentFactory() {
super();
}
@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 -> {
SystemUIFactory.createFromConfig(context);
SystemUIFactory.getInstance().getRootComponent().inject(
SystemUIAppComponentFactory.this);
}
);
}
return app;
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
可以看到,SystemUIAppComponentFactory继承了AppComponentFactory,但是重写的是instantiateApplicationCompat(),而不是instantiateApplication()方法,注意一下:AppComponentFactory对应的是androidx.core.app.AppComponentFactory,而不是android.app.AppComponentFactory,前者继承了后者,对其进行了实现后暴露了instantiateApplicationCompat()方法,看一下androidx.core.app.AppComponentFactory实现:
@RequiresApi(28)
public class AppComponentFactory extends android.app.AppComponentFactory {
;;;;;;;;;;;;;;;;;;;;;;;;;;
/**
* @see #instantiateApplicationCompat
*/
@Override
public final Application instantiateApplication(ClassLoader cl, String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return checkCompatWrapper(instantiateApplicationCompat(cl, className));
}
public @NonNull Application instantiateApplicationCompat(@NonNull ClassLoader cl,
@NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
try {
return (Application) cl.loadClass(className).getDeclaredConstructor().newInstance();
} catch (InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException("Couldn't call constructor", e);
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
在instantiateApplication()内部会调用instantiateApplicationCompat(),然后创建Application实例;接着上面分析,在SystemUIAppComponentFactory的instantiateApplicationCompat()内部会执行三项工作:
1.调用父类方法来实例化Application;
2.调用app的setContextAvailableCallback()方法,里面会有回调方法,SystemUIApplication实现了ContextInitializer接口;
3.返回Application实例;
/**
* A callback that receives a Context when one is ready.
*/
public interface ContextAvailableCallback {
void onContextAvailable(Context context);
}
/**
* Implemented in classes that get started by the system before a context is available.
*/
public interface ContextInitializer {
void setContextAvailableCallback(ContextAvailableCallback callback);
}
关于方法回调,一会再讲,先看一下SystemUIApplication的实现:
3.SystemUIApplication.java
public class SystemUIApplication extends Application implements
SystemUIAppComponentFactory.ContextInitializer {
private ContextComponentHelper mComponentHelper;
;;;;;;;;;;;;;;;;;;;;;;
private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
private SystemUIRootComponent mRootComponent;
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "SystemUIApplication created.");
mContextAvailableCallback.onContextAvailable(this);
mRootComponent = SystemUIFactory.getInstance().getRootComponent();
mComponentHelper = mRootComponent.getContextComponentHelper();
mBootCompleteCache = mRootComponent.provideBootCacheImpl();
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
@Override
public void setContextAvailableCallback(
SystemUIAppComponentFactory.ContextAvailableCallback callback) {
mContextAvailableCallback = callback;
}
前面在分析ActivityThread相关的逻辑时讲到,在handlebindApplication()时,先创建application实例,然后attach(context),最后执行onCreate(),根据SystemUIAppComponentFactory内部的执行逻辑可以看到,在instantiateApplicationCompat()内部先创建application对象,然后执行setContextAvailableCallback()赋值给SystemUIApplication,当SystemUIApplication执行到onCreate()时,执行onContextAvailable()回调,然后SystemUIAppComponentFactory内部执行初始化逻辑:
//SystemUIAppComponentFactory.java
if (app instanceof ContextInitializer) {
((ContextInitializer) app).setContextAvailableCallback(
context -> {
SystemUIFactory.createFromConfig(context);
SystemUIFactory.getInstance().getRootComponent().inject(
SystemUIAppComponentFactory.this);
}
);
}
在回调中主要执行了两项工作,都与SystemUIFactory有关,一起来看一下SystemUIFactory实现:
4.SystemUIFactory.java
public class SystemUIFactory {
public static void createFromConfig(Context context) {
if (mFactory != null) {
return;
}
final String clsName = context.getString(R.string.config_systemUIFactoryComponent);
if (clsName == null || clsName.length() == 0) {
throw new RuntimeException("No SystemUIFactory component configured");
}
try {
Class<?> cls = null;
cls = context.getClassLoader().loadClass(clsName);
mFactory = (SystemUIFactory) cls.newInstance();
mFactory.init(context);
} catch (Throwable t) {
Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
throw new RuntimeException(t);
}
}
在createFromConfig()内部,会创建SystemUIFactory实例,然后执行init()方法,context对应的是SystemUIApplication this对象;
private void init(Context context) {
mRootComponent = buildSystemUIRootComponent(context);
// Every other part of our codebase currently relies on Dependency, so we
// really need to ensure the Dependency gets initialized early on.
Dependency dependency = new Dependency();
mRootComponent.createDependency().createSystemUI(dependency);
dependency.start();
}
在init()内部主要执行了四项工作:
1.通过buildSystemUIRootComponent()获取SystemUIRootComponent对象;
2.创建Dependency实例;
3.执行createSystemUI():初始化Dependency内部含@Inject的变量;
4.执行Dependency的start()方法;
接着上面SystemUIAppComponentFactory回调方法分析,在执行完SystemUIFactory.createFromConfig(),会执行
SystemUIFactory.getInstance().getRootComponent().inject(SystemUIAppComponentFactory.this):初始化SystemUIAppComponentFactory内部含@Inject的变量;
以上涉及到dagger2知识,主要是为了解耦,用了APT(注解处理器),在编译时帮忙生成许多类来简化代码,加上注解后,会自动帮忙创建类对象等,这里就不展开讲了,主要是完成了一些初始化工作;
前面讲到,system_server是通过startServiceAsUser()来启动的SystemUI进程,在SystemUIApplication初始化后完成后,会执行到SystemUISerivice里面的逻辑:
5.SystemUIService.java
public class SystemUIService extends Service {
;;;;;;;;;;;;;;;;;;;;;;
@Override
public void onCreate() {
super.onCreate();
// Start all of SystemUI
((SystemUIApplication) getApplication()).startServicesIfNeeded();
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
}
可以看到,在SystemUIService的onCreate()内部,会获取到SystemUIApplication实例,然后执行startServicesIfNeeded():
//SystemUIApplication
public void startServicesIfNeeded() {
String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
}
//SystemUIFactory.java
public String[] getSystemUIServiceComponents(Resources resources) {
return resources.getStringArray(R.array.config_systemUIServiceComponents);
}
<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
;;;;;;;;;;;;;;;;;;;;;;;;;;
<item>com.android.systemui.recents.Recents</item>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
<item>com.android.systemui.statusbar.phone.StatusBar</item>
;;;;;;;;;;;;;;;;;;;;;;;;;;
</string-array>
获取到的systemUIServiceComponents是一些实现了SystemUI的类,然后调用startServicesIfNeeded():
//SystemUIApplication.java
private void startServicesIfNeeded(String metricsPrefix, String[] services) {
if (mServicesStarted) {
return;
}
mServices = new SystemUI[services.length];
;;;;;;;;;;;;;;;;;;;;;;;;;
final int N = services.length;
for (int i = 0; i < N; i++) {
String clsName = services[i];
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;
}
mServices[i].start();
if (mBootCompleteCache.isBootComplete()) {
mServices[i].onBootCompleted();
}
}
mServicesStarted = true;
}
可以看到,在startServicesIfNeeded()会进行遍历来创建SystemUI子类对象,然后将实例赋值给mServices数组,接着执行start()方法,最后执行onBootCompleted();
用一张流程图总结一下:
image.png
以上就是SystemUI进程启动的主要流程,SystemUI相关的子类进行各种逻辑初始化处理都是在start()及onBootCompleted()里面进行。
四.CarSystemUI
CarSystemUI是针对Car独立定制的SystemUI,即继承了SystemUI的属性,又有自己独特的属性,接下来一起看一下:
1.与SystemUI的关系
先看一下framework/base/packages/CarSystemUI/Android.bp:
android_app {
name: "CarSystemUI",
static_libs: [
"CarSystemUI-core",
],
overrides: [
"SystemUI",
],
platform_apis: true,
system_ext_specific: true,
certificate: "platform",
privileged: true,
..................
..................
}
可以看到,是对SystemUI进行了覆盖,再看一下依赖库CarSystemUI-core的编译实现:
android_library {
name: "CarSystemUI-core",
srcs: [
"src/**/*.java",
"src/**/I*.aidl",
],
resource_dirs: [
"res-keyguard",
"res",
],
static_libs: [
"SystemUI-core",
"CarNotificationLib",
"SystemUIPluginLib",
"SystemUISharedLib",
"SettingsLib",
"car-ui-lib",
........................
],
libs: [
"android.car",
],
manifest: "AndroidManifest.xml",
plugins: ["dagger2-compiler-2.19"],
}
CarSystemUI-core包含当前src和res,并且依赖SystemUI-core库,所以CarSystemUI包含了SystemUI所有的资源。
2.独特属性
前面分析到,在SystemUIService会通过SystemUIApplication的startServicesIfNeeded()来启动一些SystemUI的子类,再回忆一下这个方法:
public void startServicesIfNeeded() {
String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
}
此处通过createFromConfig()来创建SystemUIFactory对象时,返回的是CarSystemUIFactory实例,对应的实现如下:
<string name="config_systemUIFactoryComponent" translatable="false">
com.android.systemui.CarSystemUIFactory
</string>
那么看一下CarSystemUIFactory对应的getSystemUIServiceComponents()实现:
public String[] getSystemUIServiceComponents(Resources resources) {
Set<String> names = new HashSet<>();
for (String s : super.getSystemUIServiceComponents(resources)) {
names.add(s);
}
for (String s : resources.getStringArray(R.array.config_systemUIServiceComponentsExclude)) {
names.remove(s);
}
for (String s : resources.getStringArray(R.array.config_systemUIServiceComponentsInclude)) {
names.add(s);
}
String[] finalNames = new String[names.size()];
names.toArray(finalNames);
return finalNames;
}
可以看到,在该方法内部,会先调用SystemUI的对应方法来获取names,接着移除了一些names,然后又加入了一些names,最后封装成自己需要启动的SystemUI子类集合,看一下Exclue及Include的定义:
<string-array name="config_systemUIServiceComponentsExclude" translatable="false">
<item>com.android.systemui.recents.Recents</item>
......................
<item>com.android.systemui.statusbar.phone.StatusBar</item>
.......................
</string-array>
<string-array name="config_systemUIServiceComponentsInclude" translatable="false">
<item>com.android.systemui.car.navigationbar.CarNavigationBar</item>
.............
<item>com.android.systemui.car.window.SystemUIOverlayWindowManager</item>
..................
</string-array>
可以看到,在CarSystemUI内部将Recents及StatusBar等元素都禁用了,增加了CarNavigationBar及SystemUIOverlayWindowManager等元素,接下来分析一下:
2.1.StatusBar和Recents
禁用状态栏,相关实现由CarNavigationBar来实现,禁用Recents;
2.2.CarNavigationBar
public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks {
.................
.................
// Nav bar views.
private ViewGroup mTopNavigationBarWindow;
private ViewGroup mBottomNavigationBarWindow;
private ViewGroup mLeftNavigationBarWindow;
private ViewGroup mRightNavigationBarWindow;
private CarNavigationBarView mTopNavigationBarView;
private CarNavigationBarView mBottomNavigationBarView;
private CarNavigationBarView mLeftNavigationBarView;
private CarNavigationBarView mRightNavigationBarView;
...............
private void createNavigationBar(RegisterStatusBarResult result) {
buildNavBarWindows();
buildNavBarContent();
attachNavBarWindows();
// Try setting up the initial state of the nav bar if applicable.
if (result != null) {
setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken,
result.mImeWindowVis, result.mImeBackDisposition,
result.mShowImeSwitcher);
}
}
private void buildNavBarContent() {
mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser());
if (mTopNavigationBarView != null) {
mTopNavigationBarWindow.addView(mTopNavigationBarView);
}
mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser());
if (mBottomNavigationBarView != null) {
mBottomNavigationBarWindow.addView(mBottomNavigationBarView);
}
mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser());
if (mLeftNavigationBarView != null) {
mLeftNavigationBarWindow.addView(mLeftNavigationBarView);
}
mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser());
if (mRightNavigationBarView != null) {
mRightNavigationBarWindow.addView(mRightNavigationBarView);
}
}
....................
}
可以看到,在CarNavigationBar内部可以显示4个NavigationBarWindow,可以对其进行配置,默认配置如下:
<bool name="config_enableTopNavigationBar">true</bool>
<bool name="config_enableLeftNavigationBar">false</bool>
<bool name="config_enableRightNavigationBar">false</bool>
<bool name="config_enableBottomNavigationBar">true</bool>
默认是顶部和底部NavigationBar是显示的,顶部NavigationBar包含左右两边两个空调温度的按钮,点击后通知 com.android.car.hvac显示相关窗口,中间的时间按钮点击后展开设置中的快速设置,下拉显示通知;底部NavigationBar包含了7个CarNavigationButton,点击会进入对应的实现。
2.3.SystemUIOverlayWindowManager
public class SystemUIOverlayWindowManager extends SystemUI {
..................
private final OverlayViewGlobalStateController mOverlayViewGlobalStateController;
...................
@Inject
public SystemUIOverlayWindowManager(
Context context,
Map<Class<?>, Provider<OverlayViewMediator>> contentMediatorCreators,
OverlayViewGlobalStateController overlayViewGlobalStateController) {
super(context);
mContentMediatorCreators = contentMediatorCreators;
mOverlayViewGlobalStateController = overlayViewGlobalStateController;
}
@Override
public void start() {
String[] names = mContext.getResources().getStringArray(
R.array.config_carSystemUIOverlayViewsMediators);
startServices(names);
}
private void startServices(String[] services) {
for (String clsName : services) {
long ti = System.currentTimeMillis();
try {
OverlayViewMediator obj = resolveContentMediator(clsName);
if (obj == null) {
Constructor constructor = Class.forName(clsName).getConstructor(Context.class);
obj = (OverlayViewMediator) constructor.newInstance(this);
}
mOverlayViewGlobalStateController.registerMediator(obj);
}
..................
}
}
在构造方法内,会实例化OverlayViewGlobalStateController,在start()内部会获取config_carSystemUIOverlayViewsMediators,看一下实现:
<string-array name="config_carSystemUIOverlayViewsMediators" translatable="false">
<item>@string/config_notificationPanelViewMediator</item>
<item>com.android.systemui.car.keyguard.CarKeyguardViewMediator</item>
<item>com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator</item>
<item>com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator</item>
</string-array>
<string name="config_notificationPanelViewMediator" translatable="false">
com.android.systemui.car.notification.TopNotificationPanelViewMediator</string>
实例化了OverlayViewMediator子类,并通过OverlayViewGlobalStateController的registerMediator进行注册,TopNotificationPanelViewMediator主要用来下拉显示通知;
2.4.OverlayViewGlobalStateController
管理SystemUIOverlayWindow,比如下拉通知就是通过该类来进行相关显示或隐藏的;
2.5.NotificationPanelViewController
控制通知中心
2.6.CarNavigationBarView
NavigationBar对应的View
2.7.CarNavigationBarController
控制NavigationBar的显示及隐藏等;
2.8.CarNavigationButton
NavigationBar上显示的按钮;
以上大概介绍了CarSystemUI的相关属性,详细了解需要进一步阅读源码!