Android 12 system source code_SystemUI (1) SystemUI startup process

foreword

Android's SystemUI is actually the Android system interface, which includes the status bar at the top of the interface, the Navigation Bar at the bottom, Keyguard on the lock screen, PowerUI on the power supply, Recent Task on the recent task interface, and so on. In the source code of the Andorid system, package/apps release some built-in apps of the system, such as settings, camera, Phone, Message and so on. And under framework/base/package, they are also system apps, and SystemUI is in this directory. It controls the interface of the entire Android system, but in fact it is also an app. Unlike ordinary apps, it cannot be uninstalled or replaced by third-party applications. For users, the changes to SystemUI are the most intuitive. Therefore, each Android version has relatively large changes in SystemUI. For developers, it is very important to understand Android SystemUI to optimize the Android system interface and improve user experience. Because SystemUI is a system application, it is also an APK with an entry Application, but it is started by the SystemServer process.

1. Start SystemUIService in the SystemServer process after the system starts

1. After the Android system, the system will first start a process named Zygote, and the Zygote process will start the SystemServer process, and SystemServer will start SystemUI. Here we first look at the main() method of SystemServer. The main method is as follows:

frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {
    
    
	public static void main(String[] args) {
    
    
	    new SystemServer().run();
	}
}

2. The run() method is started in the main method, and the startOtherServices() method is called in the run method:

public final class SystemServer implements Dumpable {
    
    
	private void run(){
    
    
	    	...代码省略...
	        // Start services.
	        try {
    
    
	            t.traceBegin("StartServices");
	            startBootstrapServices(t);//启动引导服务
	            startCoreServices(t);//启动核心服务
	            startOtherServices(t);//启动其他服务
	        } catch (Throwable ex) {
    
    
	            Slog.e("System", "******************************************");
	            Slog.e("System", "************ Failure starting system services", ex);
	            throw ex;
	        } finally {
    
    
	            t.traceEnd(); // StartServices
	        }
	    	...代码省略...
	}
}

3. In the startOtherServices() method, the systemReady callback method of mActivityManagerService will create a thread to execute the startSystemUi method:

public final class SystemServer implements Dumpable {
    
    
    private void startOtherServices() {
    
    
            mActivityManagerService.systemReady(() -> {
    
    
          		...代码省略...
		        try {
    
    
		            startSystemUi(context, windowManagerF);
		        } catch (Throwable e) {
    
    
		            reportWtf("starting System UI", e);
		        }
          		...代码省略...
          }
    }
}

4. The code of the startSystemUi method is as follows:

public final class SystemServer implements Dumpable {
    
    
    //启动SystemUI
    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);
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.SYSTEM);
        windowManager.onSystemUiStarted();
    }
 }

You can see that startSystemUi first obtains the PackageManagerInternal object instance pm, then calls the getSystemUiServiceComponent method of pm to obtain the path of the SystemUIService component, and finally calls the startServiceAsUser method to start the SystemUIService service.

5. PackageManagerInternal used in the startSystemUi method is an abstract class, and getSystemUiServiceComponent is also an abstract method:

frameworks/base/services/core/java/android/content/pm/PackageManagerInternal.java

public abstract class PackageManagerInternal implements PackageSettingsSnapshotProvider {
    
    

    ...代码省略...
    /**
     * 抽象方法,返回SystemUI 服务组件的名称
     */
    public abstract ComponentName getSystemUiServiceComponent();
    
    ...代码省略...
}

To know the specific path of SystemUiService, we need to know who implemented the getSystemUiServiceComponent method.

6. The internal class PackageManagerInternalImpl of PackageManagerService inherits the abstract class PackageManagerInternal and implements the getSystemUiServiceComponent method:

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

    private class PackageManagerInternalImpl extends PackageManagerInternal {
    
    
    	...代码省略...
        public ComponentName getSystemUiServiceComponent() {
    
    
            return ComponentName.unflattenFromString(mContext.getResources().getString(
                    com.android.internal.R.string.config_systemUIServiceComponent));
        }
        ...代码省略...
   }

It can be seen that ComonentName obtains the complete class name of the SystemUIService component from an internal resource string com.android.internal.R.string.config_systemUIServiceComponent.

7. By searching, you can find the specific location and content of the resource string of config_systemUIServiceComponent:

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

<!-- SystemUI服务组件-->
<string name="config_systemUIServiceComponent" translatable="false">com.android.systemui/com.android.systemui.SystemUIService</string>

2. SystemUIApplication is started and executes the callback method set by the application component factory SystemUIAppComponentFactory

1. The path of the SystemUI module in the source code is framework/base/package/SystemUI. In essence, it is also an APK with higher permissions and resident memory. It also has an entry Application and an AndroidManifest.xml manifest configuration file:

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/icon"
        android:process="com.android.systemui"
        android:supportsRtl="true"
        android:theme="@style/Theme.SystemUI"
        android:defaultToDeviceProtectedStorage="true"
        android:directBootAware="true"
        tools:replace="android:appComponentFactory"
        android:appComponentFactory=".SystemUIAppComponentFactory">
		...代码省略...	
        <service android:name="SystemUIService"android:exported="true"/>   
        ...代码省略...     
    </application>
</manifest>

The above list file mainly has the following points worthy of our attention:

  • The entry of SystemUI is SystemUIApplication.
  • SystemUI is a persistent (persistent) application. When the application crashes due to an exception, the system will restart the application.
  • The application component factory attribute appComponentFactory points to SystemUIAppComponentFactory.
  • The declaration of the SystemUIService service, and supports external calling.

2. We know that before starting a service, the Android system will first detect whether the process corresponding to the service exists. If it does not exist, it will create a process. When the SystemServer process starts the SystemUiService service, it also needs to first detect the corresponding SystemUIService Whether the process exists; since it is started for the first time, the SystemUI process naturally does not exist, then the Android system will first create the SystemUI process, and enter the main method of the ActivityThread class representing the main thread in the process, and then trigger the ActivityThread A more critical method handleBindApplication:

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {
    
    
	...代码省略...
    private void handleBindApplication(AppBindData data) {
    
    
        ...代码省略...
        //获取Application的实例对象
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        ...代码省略...
        //调用Application的onCreate()方法
         mInstrumentation.callApplicationOnCreate(app);
        ...代码省略...
   }

The handleBindApplication method of ActivityThread first calls the data.info.makeApplication method to obtain the Application instance object. For SystemUI, it is actually SystemUIApplication. The SystemUIApplication instance object is finally obtained by calling the makeApplication method through the data.info object of type LoadedApk.

3. The key code of the makeApplication method of LoadedApk is as follows:

frameworks/base/core/java/android/app/LoadedApk.java


    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
    
    
        //如果已经创建了Application,就直接返回
        if (mApplication != null) {
    
    
            return mApplication;
        }
        ...代码省略...
        try {
    
    
            ...代码省略...
            //创建Application的Context
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //继续调用Instrumentation的newApplication方法创建Application
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
    
    
            ...代码省略...
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        ...代码省略...
        return app;
     }

The makeApplication method of LoadedApk will call the newApplication method of Instrumentation again to obtain the Application instance object.

4. The key code of the newApplication method of Instrumentation is as follows:

frameworks/base/core/java/android/app/Instrumentation.java

public class Instrumentation {
    
    
	...代码省略...
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
    
    
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }

   private AppComponentFactory getFactory(String pkg) {
    
    
      if (pkg == null) {
    
    
          Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
          return AppComponentFactory.DEFAULT;
      }
      if (mThread == null) {
    
    
          Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
                  + " disabling AppComponentFactory", new Throwable());
          return AppComponentFactory.DEFAULT;
      }
      LoadedApk apk = mThread.peekPackageInfo(pkg, true);
      // This is in the case of starting up "android".
      if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
      return apk.getAppFactory();
  }
}

newApplication will first call the getFactory method, and the getFactory method will determine whether pkg and mThread of type ActivityThead are empty, and if it is empty, it will directly return the DEFAULT attribute of AppComponentFactory:

frameworks/base/core/java/android/app/AppComponentFactory.java

public class AppComponentFactory {
    
    
	...代码省略...
    public static final AppComponentFactory DEFAULT = new AppComponentFactory();
}

In fact, it is an instance object of AppComponentFactory; if mThread is not empty, the getAppFactory method of LoadedApk will be called.

5. The key code associated with LoadedApk and getAppFactory is as follows:

public final class LoadedApk {
    
    
    private AppComponentFactory mAppComponentFactory;
    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;
    }
    
    public AppComponentFactory getAppFactory() {
    
    
        return mAppComponentFactory;
    }

getAppFactory directly returns the attribute variable mAppComponentFactory of LoadedApk. mAppComponentFactory was first assigned through the createAppFactory method. In fact, the object configured by the appComponentFactory attribute in AndroidManifest.xml is instantiated through reflection and assigned to mAppComponentFactory. Combined with the AndroidManifest.xml file of the previous SystemUI module, it can be seen that the property of appComponentFactory is SystemUIAppComponentFactory. Going back to the previous step 4, the newApplication method of Instrumentation will call the instantiateApplicationCompat method of the object to obtain the SystemUIApplication instance object after calling getFactory to obtain the SystemUIAppComponentFactory instance object.

6. SystemUIAppComponentFactory is a custom application component factory inherited from AppComponentFactory by the SystemUI module. The instantiateApplicationCompat method of this class is as follows:

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java

import androidx.core.app.AppComponentFactory;
public class SystemUIAppComponentFactory extends AppComponentFactory {
    
    
	...代码省略...
    @NonNull
    @Override
    public Application instantiateApplicationCompat(
            @NonNull ClassLoader cl, @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    
    
         //获取Application的实例对象
        Application app = super.instantiateApplicationCompat(cl, className);
        if (app instanceof ContextInitializer) {
    
    
        //为Application设置回调方法
            ((ContextInitializer) app).setContextAvailableCallback(
                    context -> {
    
    
                        SystemUIFactory.createFromConfig(context);
                        SystemUIFactory.getInstance().getSysUIComponent().inject(SystemUIAppComponentFactory.this);
                    }
            );
        }
        return app;
    }
	...代码省略...
}

SystemUIAppComponentFactory first calls instantiateApplicationCompat of the parent class to obtain the SystemUIApplication instance object, and then calls the setContextAvailableCallback method of the object to set the callback method for the object.

7. Return to the previous step 2 again, in the handleBindApplication method of ActivityThread:

public final class ActivityThread extends ClientTransactionHandler {
    
    
	...代码省略...
    private void handleBindApplication(AppBindData data) {
    
    
        ...代码省略...
        //获取Application的实例对象
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        ...代码省略...
        //调用Application的onCreate()方法
         mInstrumentation.callApplicationOnCreate(app);
        ...代码省略...

After obtaining the instance of SystemUIApplication, it will continue to call the callApplicationOnCreate method of Instrumentation.

8. The callApplicationOnCreate method of Instrumentation is as follows:

public class Instrumentation {
    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }
}

The callApplicationOnCreate method will trigger the onCreate method of SystemUIApplication.

9. The onCreate method of SystemUIApplication is as follows:

public class SystemUIApplication extends Application implements
        SystemUIAppComponentFactory.ContextInitializer {
    
    
   ...代码省略...
   private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
   ...代码省略...
    @Override
    public void onCreate() {
    
    
        super.onCreate();
         ...代码省略...
        //执行在SystemUIAppComponentFactory方法中设置的回调对象的onContextAvailable方法
        mContextAvailableCallback.onContextAvailable(this);
        ...代码省略...        
    }

  ...代码省略...
  //SystemUIAppComponentFactory设置回调就是调用的这个方法
      @Override
  public void setContextAvailableCallback(SystemUIAppComponentFactory.ContextAvailableCallback callback) {
    
    
        mContextAvailableCallback = callback;
  }
}

The onCreate of SystemUIApplication will call the onContextAvailable method of the callback object mContextAvailableCallback.

3. SystemUIFactory creates various Dagger2 components required by the SystemUI module

1. In step 6 of the second section, we mentioned the key code corresponding to the SystemUIAppComponentFactory setting callback method for SystemUIApplication:

    	 //为Application设置回调方法
        ((ContextInitializer) app).setContextAvailableCallback(
                context -> {
    
    
                    SystemUIFactory.createFromConfig(context);
                    SystemUIFactory.getInstance().getSysUIComponent().inject(SystemUIAppComponentFactory.this);
                }
        );

SystemUIApplication's onCreate calls back this method, which first executes the createFromConfig method of SystemUIFactory. The main function of createFromConfig is to create an instance object of SystemUIFactory. The relevant code of SystemUIFactory's createFromConfig method is as follows:

public class SystemUIFactory {
    
    

    static SystemUIFactory mFactory;
    public static void createFromConfig(Context context) {
    
    
        createFromConfig(context, false);
    }

    @VisibleForTesting
    public static void createFromConfig(Context context, boolean fromTest) {
    
    
        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);
            //创建SystemUIFactory实例
            mFactory = (SystemUIFactory) cls.newInstance();
            //执行init方法
            mFactory.init(context, fromTest);
        } catch (Throwable t) {
    
    
            Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
            throw new RuntimeException(t);
        }
    }
}

The createFromConfig method will further call the createFromConfig(context, false) method, which first obtains the string corresponding to R.string.config_systemUIFactoryComponent:

frameworks/base/packages/SystemUI/res/values/config.xml

    <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>

What config_systemUIFactoryComponent stores is the class name of SystemUIFactory. After obtaining the string, it will convert the string into a SystemUIFactory instance object through reflection, and execute the init method. Here it is obvious that the static method of SystemUIFactory can be executed, why do we need to create an instance object through the class name path? The reason for this design is actually for developers to embed a custom SystemUIFactory component factory in the project.

2. The code related to SystemUIFactory and init method is as follows:

public class SystemUIFactory {
    
    

    private GlobalRootComponent mRootComponent;//SystemUI应用的Dagger2根组件
    private WMComponent mWMComponent;//和WindowManager有关的Dagger2子组件
    private SysUIComponent mSysUIComponent;//和SystemUI核心组件有关的Dagger2子组件
    private boolean mInitializeComponents;//是否对组件进行初始化

	//初始化SystemUI模块的所有Dagger2组件
    @VisibleForTesting
    public void init(Context context, boolean fromTest)
            throws ExecutionException, InterruptedException {
    
    
        // 如果不是为了进行测试、且应用属于System用户组、进程名和com.andorid.systemui相等
        mInitializeComponents = !fromTest
                && android.os.Process.myUserHandle().isSystem()
                && ActivityThread.currentProcessName().equals(ActivityThread.currentPackageName());
        //构建本地根组件GlobalRootComponent实例对象
        mRootComponent = buildGlobalRootComponent(context);
        //构建子组件WMComponent实例对象
        mWMComponent = mRootComponent.getWMComponentBuilder().build();
        if (mInitializeComponents) {
    
    
        	//WMComponent子组件初始化
            mWMComponent.init();
        }
        //获取SysUIComponent的建造者
        SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();
        if (mInitializeComponents) {
    
    
        	//调用prepareSysUIComponentBuilder返回SysUIComponent的建造者
            builder = prepareSysUIComponentBuilder(builder, mWMComponent)
                    .setPip(mWMComponent.getPip())
                    .setLegacySplitScreen(mWMComponent.getLegacySplitScreen())
                    .setSplitScreen(mWMComponent.getSplitScreen())
                    .setOneHanded(mWMComponent.getOneHanded())
                    .setBubbles(mWMComponent.getBubbles())
                    .setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
                    .setShellCommandHandler(mWMComponent.getShellCommandHandler())
                    .setAppPairs(mWMComponent.getAppPairs())
                    .setTaskViewFactory(mWMComponent.getTaskViewFactory())
                    .setTransitions(mWMComponent.getTransitions())
                    .setStartingSurface(mWMComponent.getStartingSurface())
                    .setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
                    .setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper())
                    .setRecentTasks(mWMComponent.getRecentTasks())
                    .setCompatUI(Optional.of(mWMComponent.getCompatUI()))
                    .setDragAndDrop(Optional.of(mWMComponent.getDragAndDrop()));
        } else {
    
    
       		...代码省略...
        }
        //构建SysUIComponent实例对象
        mSysUIComponent = builder.build();
        if (mInitializeComponents) {
    
    
        	//SysUIComponent子组件初始化
            mSysUIComponent.init();
        }
        //创建Dependency实例,不同组件之间沟通的桥梁
        Dependency dependency = mSysUIComponent.createDependency();
        //初始化Dependency
        dependency.start();
    }
}

The init method is mainly to obtain the only Dagger2 root component mRootComponent of the SystemUI module, the Dagger2 subcomponent mWMComponent related to WindowManager, and the Dagger2 subcomponent mSysUIComponent related to the SystemUI core component, initialize these three components, and finally create a Dependency instance object And to initialize, Dependency is a bridge for communication between different components of the SystemUI module.

3. Continue to look at the callback method set by SystemUIAppComponentFactory for SystemUIApplication:

    	 //为Application设置回调方法
        ((ContextInitializer) app).setContextAvailableCallback(
                context -> {
    
    
                    SystemUIFactory.createFromConfig(context);
                    SystemUIFactory.getInstance().getSysUIComponent().inject(SystemUIAppComponentFactory.this);
                }
        );

After executing the createFromConfig method of SystemUIFactory to create the SystemUIFactory instance object, obtain various Dagger2 components and initialize them, the getSysUIComponent method of SystemUIFactory will be called to obtain the SysUIComponent instance object, and the inject(SystemUIAppComponentFactory factory) method of the instance object will be called to rely on the SystemUIAppComponentFactory object injection.

4. Key codes of SysUIComponent and inject (SystemUIAppComponentFactory factory) methods:

frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java

@SysUISingleton//单例
@Subcomponent(//子组件
modules = {
    
    //当前连接组件用到的Module(Module会提供我们需要的各种对象实例)
        DefaultComponentBinder.class,
        DependencyProvider.class,
        SystemUIBinder.class,
        SystemUIModule.class,
        SystemUIDefaultModule.class})
public interface SysUIComponent {
    
    
	//调用这个方法对SystemUIAppComponentFactory进行依赖注入
    void inject(SystemUIAppComponentFactory factory);
 }

After the inject(SystemUIAppComponentFactory factory) method of SysUIComponent is executed, the attribute variables marked by @Inject annotation in the SystemUIAppComponentFactory class will be assigned. In fact, there is only one attribute variable mComponentHelper marked by @Inject annotation in the SystemUIAppComponentFactory class:

public class SystemUIAppComponentFactory extends AppComponentFactory {
    
    
    @Inject
    public ContextComponentHelper mComponentHelper;//Dagger2依赖注入会对这个对象进行赋值
}

After the inject method is executed, the mComponentHelper attribute of type ContextComponentHelper will be assigned. The ContextComponentHelper class provides a method to obtain the instance object of the common class of the SystemUI module:

frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java

public interface ContextComponentHelper {
    
    

    Activity resolveActivity(String className);

    RecentsImplementation resolveRecents(String className);

    Service resolveService(String className);

    SystemUI resolveSystemUI(String className);

    BroadcastReceiver resolveBroadcastReceiver(String className);
}

The ContextComponentHelper interface provides five methods, which respectively return instance objects of the Activity, RecentsImplementation, Service, SystemUI, and BroadcastReceiver types through the class name. This interface currently has only one implementation class, 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<SystemUI>> mSystemUICreators;
    private final Map<Class<?>, Provider<RecentsImplementation>> mRecentsCreators;
    private final Map<Class<?>, Provider<BroadcastReceiver>> mBroadcastReceiverCreators;

	//由于构造方法添加了@Inject注解
	//mActivityCreators、mServiceCreators、mSystemUICreators、mRecentsCreators、mBroadcastReceiverCreators都会被实例化
    @Inject
    ContextComponentResolver(Map<Class<?>, Provider<Activity>> activityCreators,
            Map<Class<?>, Provider<Service>> serviceCreators,
            Map<Class<?>, Provider<SystemUI>> systemUICreators,
            Map<Class<?>, Provider<RecentsImplementation>> recentsCreators,
            Map<Class<?>, Provider<BroadcastReceiver>> broadcastReceiverCreators) {
    
    
        mActivityCreators = activityCreators;
        mServiceCreators = serviceCreators;
        mSystemUICreators = systemUICreators;
        mRecentsCreators = recentsCreators;
        mBroadcastReceiverCreators = broadcastReceiverCreators;
    }
	//通过类名获取Activity实例对象
    @Override
    public Activity resolveActivity(String className) {
    
    
        return resolve(className, mActivityCreators);
    }
	//通过类名获取BroadcastReceiver实例对象
    @Override
    public BroadcastReceiver resolveBroadcastReceiver(String className) {
    
    
        return resolve(className, mBroadcastReceiverCreators);
    }
	//通过类名获取RecentsImplementation实例对象
    @Override
    public RecentsImplementation resolveRecents(String className) {
    
    
        return resolve(className, mRecentsCreators);
    }
	//通过类名获取Service实例对象
    @Override
    public Service resolveService(String className) {
    
    
        return resolve(className, mServiceCreators);
    }
	//通过类名获取SystemUI实例对象
    @Override
    public SystemUI resolveSystemUI(String className) {
    
    
        return resolve(className, mSystemUICreators);
    }

    // 依据名称得到的class类名去查询Provider实例,进而取得class类名对应实例对象
    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;
        }
    }
}

Since the @Inject annotation is added to the construction method of ContextComponentResolver, mActivityCreators, mServiceCreators, mSystemUICreators, mRecentsCreators, mBroadcastReceiverCreators will be instantiated, and subsequent other classes can obtain className by calling these five methods: resolveActivity, resolveBroadcastReceiver, resolveRecents, resolveService, and resolveSystemUI The corresponding Activity, BroadcastReceiver, RecentsImplementation, Service, and SystemUI instance objects; especially the resolveSystemUI method, which we will use next.

5. Let’s use a picture to summarize the source code calling process of the previous three sections:
insert image description here
Then use a few short sentences to summarize the previous three sections:

Before starting the SystemUIService service, SystemServer detects that the process corresponding to the service does not exist, so it creates the process and the SystemUIApplication corresponding to the process, executes the onCreate method of SystemUIApplication, and executes the callback method set by SystemUIAppComponentFactory. The createFromConfig method of SystemUIFactory is called in the method to create all Dagger2 components of the SystemUI module.

4. Start all components required by the SystemUI module in SystemUIService.

1. In step 9 of the second section above, we said that the callback method set by SystemUIAppComponentFactory will be executed in the onCreate method of SystemUIApplication. After the callback method is executed, the onCreate method of SystemUIApplication will continue to execute:

public class SystemUIApplication extends Application implements
        SystemUIAppComponentFactory.ContextInitializer {
    
    
   ...代码省略...
    private ContextComponentHelper mComponentHelper;//前面有介绍过这个类,调用这个类的方法可以获取到SystemUI模块的各种实例对象
    private BootCompleteCacheImpl mBootCompleteCache;
    private SystemUI[] mServices;//SystemUI模块的各种SystemUI组件
    private boolean mServicesStarted;//组件是否已经被启动
    private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;//回调方法
    private GlobalRootComponent mRootComponent;//根组件
    private SysUIComponent mSysUIComponent;//SystemUI子组件
   ...代码省略...
    @Override
    public void onCreate() {
    
    
        super.onCreate();
         ...代码省略...
        //执行在SystemUIAppComponentFactory方法中设置的回调
        mContextAvailableCallback.onContextAvailable(this);
        //对成员变量进行赋值
        mRootComponent = SystemUIFactory.getInstance().getRootComponent();
        mSysUIComponent = SystemUIFactory.getInstance().getSysUIComponent();
        mComponentHelper = mSysUIComponent.getContextComponentHelper();
        mBootCompleteCache = mSysUIComponent.provideBootCacheImpl();
        ...代码省略...        
        if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
    
    
           ...代码省略...
            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++) {
    
    
                            mServices[i].onBootCompleted();
                        }
                    }
                }
            }, bootCompletedFilter);
           ...代码省略...
        } else {
    
    
           ...代码省略...
            startSecondaryUserServicesIfNeeded();
        }
    }

The onCreate method of SystemUIApplication will do some initialization operations, and then two branches will appear due to an ifi condition judgment.
1) If it is started by the system (started by SystemServer), it will enter this branch, register to monitor the notification of boot completed, and finally call back each component onBootCompleted after it is fully started.
2) If the system is not started, such as the case of multi-user login and use, the system has actually started at this time, and it will go to the else branch to enter startSecondaryUserServicesIfNeeded() to start the service components required by SystemUI. This branch is based on user to start the corresponding service.

Since SystemUI is started by SystemServer here, the first case will be executed.

2. As mentioned above, SystemServer finally waits until the onCreate method of SystemUIApplication is executed. At this time, the system will actually start the service SystemUIService that SystemServer wants to start. After SystemUIService is started, it will execute the onCreate method immediately:

frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

public class SystemUIService extends Service {
    
    
    ...代码省略...
    @Override
    public void onCreate() {
    
    
        super.onCreate();
        // 启动SystemUI的全部组件
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
   }
   ...代码省略...
}

The onCreate method of SystemUIService will reacquire the SystemUIApplication instance object and call the startServicesIfNeeded method of the object.

3. The startServicesIfNeeded() method of SystemUIApplication is as follows:

public class SystemUIApplication extends Application implements
        SystemUIAppComponentFactory.ContextInitializer {
    
    
   ...代码省略...
 public void startServicesIfNeeded() {
    
    
        String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
        startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
    }
   ...代码省略...
}

5. The startServicesIfNeeded of SystemUIApplication first calls getSystemUIServiceComponents through SystemUIFactory to obtain a string array and assign it to names:

framework/base/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java

public class SystemUIFactory {
    
    
   ...代码省略...	
    public String[] getSystemUIServiceComponents(Resources resources) {
    
    
        return resources.getStringArray(R.array.config_systemUIServiceComponents);
    }
   ...代码省略...    
}

R.array.config_systemUIServiceComponents stores all the components that need to be started by the SystemUI module:

framework/base/packages/SystemUI/res/values/config.xml

    <string-array name="config_systemUIServiceComponents" translatable="false">
        <item>com.android.systemui.util.NotificationChannels</item><!--通知-->
        <item>com.android.systemui.keyguard.KeyguardViewMediator</item><!--键盘锁状态-->
        <item>com.android.systemui.recents.Recents</item><!--任务列表-->
        <item>com.android.systemui.volume.VolumeUI</item><!--监听音量,并决定是否显示音量的对话框-->
        <item>com.android.systemui.statusbar.phone.StatusBar</item><!--状态栏-->
        <item>com.android.systemui.usb.StorageNotification</item><!--监听 USB 连接状态并发送通知进行提示-->
        <item>com.android.systemui.power.PowerUI</item><!--监听电量状态并在低电量时发送通知-->
        <item>com.android.systemui.media.RingtonePlayer</item><!--用于播放铃声-->
        <item>com.android.systemui.keyboard.KeyboardUI</item><!--键盘锁 UI-->
        <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item><!--快捷分发器-->
        <item>@string/config_systemUIVendorServiceComponent</item><!--这里可以定义厂商定制的组件-->
        <item>com.android.systemui.util.leak.GarbageMonitor$Service</item><!--用于监控内存泄漏的服务-->
        <item>com.android.systemui.LatencyTester</item><!--仅在 debug 环境执行,用于监听系统测试延迟的模拟动作-->
        <item>com.android.systemui.globalactions.GlobalActionsComponent</item><!--用于显示全局对话框(例如长按电源按键)-->
        <item>com.android.systemui.ScreenDecorations</item><!--处理页面中的显示的形状(如圆角)-->
        <item>com.android.systemui.biometrics.AuthController</item><!--身份验证-->
        <item>com.android.systemui.SliceBroadcastRelayHandler</item><!--允许打开设置App-->
        <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item><!--时应用程序通知-->
        <item>com.android.systemui.theme.ThemeOverlayController</item><!--主题-->
        <item>com.android.systemui.accessibility.WindowMagnification</item><!--放大器-->
        <item>com.android.systemui.accessibility.SystemActions</item>
        <item>com.android.systemui.toast.ToastUI</item>
        <item>com.android.systemui.wmshell.WMShell</item>
    </string-array>

The components mentioned above are not the four major components of Android. These components are actually just ordinary Java abstract classes, but they all inherit from the abstract class SystemUI. The code of SystemUI is as follows:

framework/base/packages/SystemUI/src/com/android/systemui/SystemUI.java

public abstract class SystemUI implements Dumpable {
    
    
    protected final Context mContext;

    public SystemUI(Context context) {
    
    
        mContext = context;
    }

    public abstract void start();

    protected void onConfigurationChanged(Configuration newConfig) {
    
    
    }

    @Override
    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
    
    
    }

    protected void onBootCompleted() {
    
    
    }

    public static void overrideNotificationAppName(Context context, Notification.Builder n,
            boolean system) {
    
    
        final Bundle extras = new Bundle();
        String appName = system
                ? context.getString(com.android.internal.R.string.notification_app_name_system)
                : context.getString(com.android.internal.R.string.notification_app_name_settings);
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName);

        n.addExtras(extras);
    }
}

6. Go back to step 3. After obtaining the array of component class names inherited from the SystemUI abstract class in the SystemUI module and assigning them to names, the startServicesIfNeeded(“StartServices”, names) method of SystemUIApplication will be called:

    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];//具体SystemUI组件类的完整路径
            long ti = System.currentTimeMillis();
            try {
    
    
                SystemUI obj = mComponentHelper.resolveSystemUI(clsName);//ComponentHelper的resolveSystemUI方法可以通过类名拿到具体的SystemUI实例对象
                if (obj == null) {
    
    //如果通过ComponentHelper的resolveSystemUI没有成功获取到实例对象,则通过反射创建,代码基本上不会走这里。
                    Constructor constructor = Class.forName(clsName).getConstructor(Context.class);
                    obj = (SystemUI) constructor.newInstance(this);//通过反射创建实例对象
                }
                mServices[i] = obj;//将获取的obj实例对象赋值到数组中。
            } catch (ClassNotFoundException
                    | NoSuchMethodException
                    | IllegalAccessException
                    | InstantiationException
                    | InvocationTargetException ex) {
    
    
                throw new RuntimeException(ex);
            }
            ...代码省略...     
            mServices[i].start();
    		...代码省略...     
            if (mBootCompleteCache.isBootComplete()) {
    
    
                mServices[i].onBootCompleted();
            }
    		...代码省略...     
        }
    	...代码省略...   
        mServicesStarted = true;//服务已经被启动
    }

To summarize the key points of the code above:

1) There is a for loop, the first sentence in the loop is to assign service[i] to clsName, and the assignment of service[i] is the specific class object path of each SystemUI

2) Call the resolveSystemUI method of ComponentHelper to obtain the SystemUI instance object corresponding to clsName and assign the object to obj.

3) If obj is null, it will continue to create the SystemUI instance object corresponding to clsName through reflection, and the code will basically not go here.

4) Store the created SystemUI instance object obj in the mServices array of type SystemUI, and call the start() method of the object to start the service of the related class. After the startup is completed, call the onBootCompleted() method of the class.

V. Summary

insert image description here

1. After the Android system is started, the Zygote process will be started first, and the Zygote process will further start the SystemServer process, which will start the services required by various systems. After the monitoring AMS is started, it will also start the SystemUIService.

2. Before starting the SystemUIService service, the system will first create the process corresponding to SystemUI, obtain the SystemUIAppComponentFactory instance object, call instantiateApplicationCompat to create the SystemUIApplication instance object and set the callback method.

3. Execute the onCreate method of SystemUIApplication, execute the callback method set by SystemUIAppComponentFactory, and call the createFromConfig method of SystemUIFactory to create and initialize the Dagger2 components required by the SystemUI module.

4. Continue to execute the onCreate method of SystemUIApplication, initialize and monitor notifications such as boot completed, and execute the onBootCompleted method of each component after the system completes startup.

5. Start the SystemUIService service and execute the onCreate method of the service. In the onCreate method of the service, the startServicesIfNeeded() method of SystemUIApplication will be called again. This method calls the resolveSystemUI method of ContextComponentHelper to obtain all SystemUI components, and execute the start method and onBootCompleted method of the component , and save them in the mServices array.

Guess you like

Origin blog.csdn.net/abc6368765/article/details/127683905