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

前言

Android 的 SystemUI 其实就是 Android 的系统界面,它包括了界面上方的状态栏 status bar,下方的导航栏Navigation Bar,下拉通知栏,下拉快捷栏,音量调控UI,电源调控UI,近期任务界面 Recent Task 等等。
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.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();
    }

}
  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.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();
    }
}
  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.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;
  }
}
  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.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();
    }

}
  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.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() {
		...代码省略...
    }

}
  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 时序图

在这里插入图片描述

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和业务逻辑。

💡 技术无价,赞赏随心

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

### Android 11 SystemUI 源码解析 #### SystemUI 应用概述 SystemUI 是以应用形式运行的个持久进程,其主要职责在于提供系统的用户界面组件,包括但不限于状态栏、通知栏、音量控制面板、快捷设置以及锁屏界面等功能。值得注意的是,尽管承担着重要角色,该应用程序并不位于 `system_server` 进程内部,而是独立存在于框架层下的特定路径中:`frameworks/base/packages/SystemUI`[^1]。 #### 下拉通知栏布局定制基础 针对 Android 11 中的 SystemUI 组件特别是下拉通知栏部分,如果开发者希望对其进行自定义,则需深入了解原有机制及其背后的源代码结构。具体来说,要熟悉两个关键文件: - **NotificationContentInflater.java**: 负责构建并填充单条通知项视图实例。 - **Notification.java**: 定义了安卓平台上的通用通知对象模型。 这两个类共同作用于通知显示逻辑的设计与实现过程之中[^2]。 #### 启动流程概览 为了更好地理解整个 SystemUI 的工作原理,可以从它的启动顺序入手。首先是通过 Zygote 初始化阶段触发 `SystemServer.main()` 方法来开启服务;随后,在完成必要的准备工作之后,会创建名为 `.SystemUIApplication` 的主程序实体,并指定相应的组件工厂用于后续扩展支持。当这个核心对象被成功建立起来以后,紧接着便是调用其中的服务管理器 `SystemUIService.onCreate()` 来激活由配置文件 config.xml 所描述的系列子系统和服务模块][^[^34]。 ```java // 示例:获取 NotificationContentInflater 实例的方式 NotificationContentInflater inflater = (NotificationContentInflater) context.getSystemService(Context.NOTIFICATION_SERVICE); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值