1. Prerequisite summary
Launcher, the desktop program, is the first application process opened after system services are started. It mainly manages the display and opening of various user apps inside the phone. During the process of opening Launcher, SystemUI such as navigation bar and other layouts are also loaded one after another. to the screen.
Launcher is started after the initialization of various system services is completed, that is, at the end of SystemServer’s startOtherService() method
2. Startup process
1. SystemServer.run()
//com.android.server.SystemServer private void run() { try{ ... //1. Create system Context createSystemContext(); ... }catch(..){..} ... try{ ... //2. Start other services startOtherServices(); ... }catch(..){..} //...... }
System services such as: AMS\ATMS, PMS, WMS, etc. are all started and initialized in the run() method of SystemServer. I will not introduce too much about the startup of system services. The main thing here is to create a system Context to prepare for subsequent startup. , and then enter the startOtherServices method
2. startOhterServices()
//com.android.server.SystemServer private void startOtherServices() { final Context context = mSystemContext; ... //Initialization of various services such as wms, ims and so on ... //Prepare for startup through AMS mActivityManagerService.systemReady(() -> { ... try { //2. Start the system UI startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } ... },BOOT_TIMINGS_TRACE_LOG); }
In the startOtherServices method, after first completing the necessary system services, AMS starts preparations for launching the Launcher. The systemReady method of AMS is called to pass in a Callback, and the system UI is started in the Callback.
3. Start SystemUI
//com.android.server.SystemServer private static void startSystemUi(Context context, WindowManagerService windowManager) { //Start system UI Service Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted(); }
Initialize the UI by starting the Service
//com.android.systemui.SystemUIService public class SystemUIService extends Service { @Override public void onCreate() { super.onCreate(); //Execute the creation method in SystemUIApplication ((SystemUIApplication) getApplication()).startServicesIfNeeded(); ... } ... }
In the onCreate() method of Service, the startServicesIfNeeded method of the current Application is called to continue initialization.
In the previous createSystemContext() method, the Context is created and the Application object is also created. The specific instance type of the Application is obtained by parsing the corresponding AndroidManifest.xml. The xml parsed by the Application created here is in /frameworks/base/packages /SystemUI package
//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" coreApp="true"> ... <application //Application class android:name=".SystemUIApplication" android:persistent="true" android:allowClearUserData="false" android:allowBackup="false" ..... </application> </manifest>
Continue execution in SystemUIApplication
//com.android.systemui.SystemUIApplication public void startServicesIfNeeded() { //Get the name that needs to initialize the system UI String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents); startServicesIfNeeded(names); } private void startServicesIfNeeded(String[] services) { if (mServicesStarted) { return; } //SystemUI collection, system UI all inherit from SystemUI mServices = new SystemUI[services.length]; ... final int N = services.length; for (int i = 0; i < N; i + + ) { String clsName = services[i]; ... Class cls; try { //Instantiate each system UI through reflection cls = Class.forName(clsName); Object o = cls.newInstance(); if (o instanceof SystemUI.Injector) { o = ((SystemUI.Injector) o).apply(this); } mServices[i] = (SystemUI) o; }...... mServices[i].mContext = this; mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); //Initialize system UI (4-1) mServices[i].start(); ... if (mBootCompleted) { mServices[i].onBootCompleted(); } } ....... }
Get the names of each SystemUI class that needs to be initialized from config.xml, then create a SystemUI array and traverse the collection to create instances through reflection, and finally call the SystemUI.start() method to initialize and render each SystemUI.
config_systemUIServiceComponents is defined in the /frameworks/base/packages/SystemUI/res/values/config.xml file, which includes a series of UIs such as the top status bar, notifications, keyboard, etc.
<!-- SystemUI Services: The classes of the stuff to start. --> <string-array name="config_systemUIServiceComponents" translatable="false"> <item>com.android.systemui.Dependency</item> <item>com.android.systemui.util.NotificationChannels</item> <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</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.stackdivider.Divider</item> <item>com.android.systemui.SystemBars</item> <item>com.android.systemui.usb.StorageNotification</item> <item>com.android.systemui.power.PowerUI</item> <item>com.android.systemui.media.RingtonePlayer</item> <item>com.android.systemui.keyboard.KeyboardUI</item> <item>com.android.systemui.pip.PipUI</item> <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> <item>com.android.systemui.globalactions.GlobalActionsComponent</item> <item>com.android.systemui.ScreenDecorations</item> <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item> <item>com.android.systemui.SliceBroadcastRelayHandler</item> </string-array>
Take SystemBars as an example:
//Inherited from SystemUI public class SystemBars extends SystemUI { ... //Start() method executed @Override public void start() { if (DEBUG) Log.d(TAG, "start"); //Create StatusBar createStatusBarFromConfig(); } ... private void createStatusBarFromConfig() { if (DEBUG) Log.d(TAG, "createStatusBarFromConfig"); //Get StatusBar class name //com.android.systemui.statusbar.phone.StatusBar final String clsName = mContext.getString(R.string.config_statusBarComponent); if (clsName == null || clsName.length() == 0) { throw andLog("No status bar component configured", null); } Class<?> cls = null; try { cls = mContext.getClassLoader().loadClass(clsName); } catch (Throwable t) { throw andLog("Error loading status bar component: " + clsName, t); } try { //Create StatusBar object through reflection mStatusBar = (SystemUI) cls.newInstance(); } catch (Throwable t) { throw andLog("Error creating status bar component: " + clsName, t); } mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; if (mStatusBar instanceof StatusBar) { SystemUIFactory.getInstance().getRootComponent() .getStatusBarInjector() .createStatusBar((StatusBar) mStatusBar); } //StatusBar also inherits SystemUI and continues to execute the start method. mStatusBar.start(); if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName()); } ... }
The StatusBar object is created in SystemBar’s start(). StatusBar is also inherited from SystemUI. Execute the start() method again.
//com.android.systemui.statusbar.phone.StatusBar //Inherit SystemUI public class StatusBar extends SystemUI implements ...{ ... @Override public void start() { ... //Get WMS mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); ... mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); ... //Create and add the view to the screen createAndAddWindows(result); ... } ... public void createAndAddWindows(@Nullable RegisterStatusBarResult result) { //Create StatusView makeStatusBarView(result); mStatusBarWindowController = Dependency.get(StatusBarWindowController.class); //Adding to Window involves WMS drawing mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight()); } }
You can see that the View is actually created in the StatusBar and drawn to the screen through WMS.
4. Start Launcher
Continue back to the SystemServer code
//com.android.server.SystemServer private void startOtherServices() { ... //Prepare for startup through AMS mActivityManagerService.systemReady(() -> { ... try { //2. Start the system UI startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } ... },BOOT_TIMINGS_TRACE_LOG); }
Enter the AMS.systemReady() method
//com.android.server.am.ActivityManagerService.java public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { synchronized(this) { if (mSystemReady) { // If it has been initialized once, execute the callback directly. if (goingCallback != null) { goingCallback.run(); } return; } mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class); //Prepare to complete configuration information mActivityTaskManager.onSystemReady(); mUserController.onSystemReady(); mAppOpsService.systemReady(); mSystemReady = true; } ... //Execute callback to initialize system UI and other operations if (goingCallback != null) goingCallback.run(); ... synchronized (this) { ... //Start Launcher mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); ... } }
Internal operations are performed to prevent multiple initialization starts. After configuring various information, call startHomeOnAllDisplays of ActivityTaskManagerInternal to start the Launcher.
Here’s a brief look at the creation process of mAtmInternal
1. mAtmInternal is the ActivityTaskManagerInternal type and manages AtivityTaskManager
Functional interface. It is obtained in the ActivityManagerService constructor
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) { ... //Get the specific implementation class through ATMI.class mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); ... }
LocalServices maintains a Map internally, which is mainly used to access some local interface services. Get the implementation class of ActivityTaskManagerInternal here.
2. ActivityTaskManagerInternal is an interface and the specific implementation class is ActivityTaskManagerService.
InternalLocalService
public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ... final class LocalService extends ActivityTaskManagerInternal { ... } ... }
3. The creation of LocalService is in the constructor of ATMS, and the addition to LocalServices is in the ATMS
When the service starts
public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ... @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public ActivityTaskManagerService(Context context) { ... mInternal = new LocalService(); ... } ... //ATMS start private void start() { //Add to LocalServices, key is ATMI.class LocalServices.addService(ActivityTaskManagerInternal.class, mInternal); } }
The startup of ATMS is carried out in SystemServer, so I won’t go into details here.
Continue back to the mAtmInternal.startHomeOnAllDisplays method
final class LocalService extends ActivityTaskManagerInternal { ... @Override public boolean startHomeOnAllDisplays(int userId, String reason) { synchronized (mGlobalLock) { //Continue executing the RootWindowContainer method return mRootWindowContainer.startHomeOnAllDisplays(userId, reason); } } ... }
RootWindowContainer.startHomeOnAllDisplays
class RootActivityContainer extends ConfigurationContainer implements DisplayManager.DisplayListener { ... boolean startHomeOnAllDisplays(int userId, String reason) { boolean homeStarted = false; for (int i = mActivityDisplays.size() - 1; i >= 0; i--) { final int displayId = mActivityDisplays.get(i).mDisplayId; //1. Obtain and continue to call the startup method homeStarted |= startHomeOnDisplay(userId, reason, displayId); } return homeStarted; } ... boolean startHomeOnDisplay(int userId, String reason, int displayId) { //2, return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */, false /* fromHomeKey */); } boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) { // Fallback to top focused display or default display if the displayId is invalid. if (displayId == INVALID_DISPLAY) { final ActivityStack stack = getTopDisplayFocusedStack(); displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY; } final DisplayContent display = getDisplayContent(displayId); boolean result = false; for (int tcNdx = display.getTaskDisplayAreaCount() - 1; tcNdx >= 0; --tcNdx) { final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tcNdx); result |= startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea, allowInstrumenting, fromHomeKey); } return result; } boolean startHomeOnTaskDisplayArea(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) { ... //Launcher's Intent Intent homeIntent = null; ActivityInfo aInfo = null; //3. Get Launcher’s Activity information if (taskDisplayArea == getDefaultTaskDisplayArea()) { homeIntent = mService.getHomeIntent(); aInfo = resolveHomeActivity(userId, homeIntent); } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) { Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea); aInfo = info.first; homeIntent = info.second; } ... //Check whether startup is allowed //There are internal judgments on the system operating mode, TopAction and split screen if (!canStartHomeOnDisplayArea(aInfo, displayId, allowInstrumenting)) { return false; } //Update Launcher's startup information homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); // Updates the extra information of the intent. if (fromHomeKey) { homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true); } // Update the reason for ANR debugging to verify if the user activity is the one that // actually launched. final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( aInfo.applicationInfo.uid) + ":" + displayId; //4. Start Launcher Activity mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, displayId); return true; } }
Finally, obtain the ActivityStartController object through ATMS and call startHomeActivity to start the Launcher.
The subsequent startup process is similar to the cold startup process of clicking the App application. The next blog will be published after the sorting is completed.
Three, finally
This article is compiled and published based on my own understanding of the Android 10 version source code. Many of the details are not detailed enough and require further understanding. If there are errors, please correct me. If you have a better process analysis, please discuss it together.