When was the virtual machine instance of the application process created? When does a process’s Binder thread pool start? Why are all application processes created by the Zygote process? The answers to these questions lie in the Android startup process. This part as the beginning of the entire system, there are a lot of knowledge points that we Android developers must understand to advance. This article will briefly comb through this process based on Android 11 code.

1. The init process starts

The Android system is based on the Linux kernel. When the user holds down the power button, the chip loads the BootLoader into memory and starts to pull up the Linux kernel. Once the Linux kernel has started, the first user-space process, init, is started. When to start the init process, get into the system/core/init/main CPP files the main method, mainly in two stages startup initialization is complete, the code is as follows:

/*system/core/init/main.cpp*/
int main(int argc, char** argv){#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#endif
    // Boost prio which will be restored later
    setpriority(PRIO_PROCESS, 0, -20);
    if(! strcmp(basename(argv[0]), "ueventd")) {
        // init creates a child process called ueventd, which is responsible for creating device nodes and setting permissions
        return ueventd_main(argc, argv);
    }

    if (argc > 1) {
        if(! strcmp(argv[1]."subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
            // Initialize the log system
            return SubcontextMain(argc, argv, &function_map);
        }

        if(! strcmp(argv[1]."selinux_setup")) {
            // Start Selinux security policy
            return SetupSelinux(argv);
        }

        if(! strcmp(argv[1]."second_stage")) {
            // Perform phase 2 startup
            returnSecondStageMain(argc, argv); }}// Perform phase 1 startup
    return FirstStageMain(argc, argv);
}
Copy the code
  • FirstStageMain(argc, argv); FirstStageMain() mainly does directory creation, device node creation, and device mounting. The simplified code is as follows:
int FirstStageMain(int argc, char** argv){... CHECKCALL(clearenv()); CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
    // Get the basic filesystem setup we need put together in the initramdisk
    // on / and then we'll let the rc file figure out the rest.
    CHECKCALL(mount("tmpfs"."/dev"."tmpfs", MS_NOSUID, "mode=0755")); // Mount the TMPFS file system
    CHECKCALL(mkdir("/dev/pts".0755));
    CHECKCALL(mkdir("/dev/socket".0755));// Create the dev/socket device node
    CHECKCALL(mkdir("/dev/dm-user".0755));
    CHECKCALL(mount("devpts"."/dev/pts"."devpts".0, NULL));// Mount the devpts filesystem. CHECKCALL(mount("sysfs"."/sys"."sysfs".0, NULL));// Mount the sysfs filesystem
    CHECKCALL(mount("selinuxfs"."/sys/fs/selinux"."selinuxfs".0, NULL));
    CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1.11)));// The KMSG device node file was created in advance to output log information. #undef CHECKCALL ...return 1;
}
Copy the code
  • SecondStageMain(argc, argv) : The main logic is to start the property service, parse the init.rc file, and start the related process.
/*system/core/init/init.cpp*/
int SecondStageMain(int argc, char** argv){... PropertyInit();// 1. Initialize the properties system and read the properties from the specified file. StartPropertyService(&property_fd);// 2. Set other system properties and enable the system property service. ActionManager& am = ActionManager::GetInstance(); ServiceList& sm = ServiceList::GetInstance(); LoadBootScripts(am, sm);// 3. Parse the init.rc file, create the rc file action and service, and start other processes.return 0;
}

static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser = CreateParser(action_manager, service_list);// Build the parser
    std::string bootscript = GetProperty("ro.boot.init_rc"."");
    if (bootscript.empty()) {
        /* Parse init.rc files of Google System, SOC vendor, ODM vendor in different paths and start related processes */
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if(! parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        parser.ParseConfig("/system_ext/etc/init");
        if(! parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
        if(! parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if(! parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init"); }}else{ parser.ParseConfig(bootscript); }}Copy the code

Load the parse RC file and start the service. Rc is a configuration file that is internally written by the Android Init Language. The script init.rc is a startup script executed after the Init process is started. The file records the operations that the init process needs to perform. Init. rc contains five main types of statements:

  • Action
  • Command
  • Service
  • Option
  • Import

How do you define zygote starting in init.rc?

2. The Zygote process is started

${ro.zygote} = ${ro.zygote} = ${ro.zygote} = ${ro.zygote}

/*system/core/rootdir/init.rc*/
import /system/etc/init/hw/init.${ro.zygote}.rc
...
on late-init
    # Now we can start zygote for devices with file based encryption
    trigger zygote-start // 1. Zygote is triggered. on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file wait_for_prop odsign.verification.done1
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start statsd
    start netd
    start zygote // 2. Start zygote
    start zygote_secondary
...
Copy the code

${ro.zygote} has four values. In the system/core/rootdir/ directory of init.rc, you can see four zygote configuration files, which represent the supported program bit:

  1. Init.zygote32. rc, the Zygote process is executed in/ system/bin/app_process
  2. Init.zygote64. rc, Zygote process execution program path is /system/bin/app_process64
  3. Zygote32_64. rc, which starts two Zygote processes with two executables, 32 as the main mode
  4. Zygote64_32. rc, which starts two Zygote processes with two executables in 64 mode (compatible with 64-bit and 32-bit applications)

Let’s take a look at the init.zygote64_32.rc file commonly used in the latest project devices:

/*system/core/rootdir/init.zygote64_32.rc*/
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote // Start 64-bit Zygote
    class main
    priority- 20user root
    group root readproc reserved_disk
    socket zygote stream 660 root system// Create a file namedzygotethesocket
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    task_profiles ProcessCapacityHigh MaxPerformance
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload // Start 32-bit zygote
    class main
    priority- 20user root
    group root readproc reserved_disk
    socket zygote_secondary stream 660 root system
    socket usap_pool_secondary stream 660 root system
    onrestart restart zygote
    task_profiles ProcessCapacityHigh MaxPerformance
Copy the code

Zygote is the name of the process. /system/bin/app_process64 is the path to the execution program. The following items are the parameters passed to the execution program. –start-system-server indicates that the system_server process needs to be started after the Zygote process starts. The Zygote process uses sockets for cross-process communication, so a socket named Zygote is created. The socket 660 indicates the access permission. Rw-rw —- indicates that the file owner and the same group user have read and write permission.

After the init process is started, start the Zygote process with fork and execv, as shown in the simplified code below:

/*system/core/init/service.cpp*/
Result<void> Service::Start(){... pid_t pid = -1;
    if (namespaces_.flags) {
        pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
    } else {
        pid = fork();// 1. Fork service (zygote)
    }
    if (pid == 0) {...if(! ExpandArgsAndExecv(args_, sigstop_)) { PLOG(ERROR) <<"cannot execv('" << args_[0] < <"'). See the 'Debugging init' section of init's README.md for tips"; }... }}static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
    std::vector<std::string> expanded_args;
    std::vector<char*> c_strings;
    expanded_args.resize(args.size());
    c_strings.push_back(const_cast<char*>(args[0].data()));
    for (std::size_t i = 1; i < args.size(); ++i) {
        auto expanded_arg = ExpandProps(args[i]);
        if(! expanded_arg.ok()) { LOG(FATAL) << args[0] < <": cannot expand arguments': " << expanded_arg.error();
        }
        expanded_args[i] = *expanded_arg;
        c_strings.push_back(expanded_args[i].data()); // Encapsulate parameters
    }
    c_strings.push_back(nullptr);
    if (sigstop) {
        kill(getpid(), SIGSTOP);
    }
    // 2. c_strings[0] is the execution program path, that is, if zygote service is started, execve will run /system/bin/app_process64
    return execv(c_strings[0], c_strings.data()) == 0;
}
Copy the code

2.1 native app_process layer

Start by running the main function at the entrance to the executable app_process:

/*frameworks/base/cmds/app_process/app_main.cpp*/
int main(int argc, char* const argv[]){...// Parse runtime arguments. Stop at first unrecognized option.
    bool zygote = false; .while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") = =0) {
            zygote = true; // Start the Zygote process
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") = =0) {
            startSystemServer = true; // Start system_server process}... }...if(! niceName.isEmpty()) { runtime.setArgv0(niceName.string(),true /* setProcName */); // Change the process name app_process to zygote
    }
    if (zygote) {
        // Start the Zygote androidRuntime. start function
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else{... }}Copy the code

Let’s take a closer look at the AndroidRuntime start process code:

/*frameworks/base/core/jni/AndroidRuntime.cpp*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n", className ! = NULL ? className :"(unknown)", getuid()); ./* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if(startVm(&mJavaVM, &env, zygote, primary_zygote) ! =0) {// 1. Start the VM
        return;
    }
    onVmCreated(env);

    /* * Register android functions. */
    if (startReg(env) < 0) { // 2. Register framework JNI calls to the virtual machine
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        // 3.JNI calls the main function that executes ZygoteInit in the Java layer
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main"."([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else{ env->CallStaticVoidMethod(startClass, startMeth, strArray); . }... }Copy the code

You can see from the code that the AndroidRun #start method does three main things:

  1. Start the process VM.

  2. Register Android framework JNI call to virtual machine;

  3. Enter the Java layer through a JNI call to execute ZygoteInit’s main function;

2.2 ZyogeInit Java layer

Let’s move on to the simplified code flow:

 /*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
 public static void main(String[] argv) {
        ZygoteServer zygoteServer = null; .try{...for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    // In the init.rc file, there is the --start-system-server parameter, indicating that SystemServer is to be created
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true; }... }...// In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if(! enableLazyPreload) { ... preload(bootTimingsTraceLog);// 1. Preload resources. }... zygoteServer =new ZygoteServer(isPrimaryZygote); // 2. Create a Socket server
            if (startSystemServer) {
                // 3.fork Starts the system_server processRunnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); . }//4. Sokcet server waits for AMS request (AMS requests Zygote through socket to create application process)
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throwex; }... }static void preload(TimingsTraceLog bootTimingsTraceLog){... preloadClasses();// 1. Load the system classes defined in system /etc/preloading-classes. preloadResources();// 2. Load all drawables and color resources defined in the system. }Copy the code

The ZygoteInit#main method starts the system_server process with the main fork:

  1. Zygote process preloads classes, theme resources, font resources, etc., based on Linux copy-on-write mechanism, so as to accelerate the startup speed of the subsequent application process created by Zygote fork.

  2. Create socket server for cross-process communication;

  3. Fork Creates and starts the system_server process.

  4. The Sokcet server enters a loop to listen and wait for subsequent AMS requests (AMS requests Zygote through sockets to create application processes).

3. Start the system_server process

We went on to ZygoteInit#forkSystemServer and looked down:

/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer){.../* Hardcoded command line to start the system server */
        // 1. Set parameters for starting the system_server process
        String[] args = {
                "--setuid=1000"."--setgid=1000"."- setgroups = 1001100 2100 3100 4100 5100 6100 7100 8100 9101 0101 8102 1102 3,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011"."--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server"."--runtime-args"."--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                // system_server Starts the class name
                "com.android.server.SystemServer"}; .try{.../* Request to fork the system server process */
            // 2.fork create system_server process, implement in native layer
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            / / 3. Pid is 0 represents in the process of the newly created system_server and continue through handleSystemServerProcess further processing
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }
    
     /** * Finish remaining work for the newly forked system server process. */
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs){...if(parsedArgs.mInvokeWith ! =null) {... }else{.../* * Pass the remaining arguments to SystemServer. */
            // call zygoteInit #zygoteInit
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }
    }
    
     public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader){.../ / 1. RuntimeInit initialization, through setting the default setDefaultUncaughtExceptionHandler exception handling mechanism
        RuntimeInit.commonInit();
        // 2. Trigger the Binder thread pool to start the process
        ZygoteInit.nativeZygoteInit();
        / / 3. Internal through layer upon layer calls, eventually through reflection to create "com. Android. Server. SystemServer" class objects and perform its main function
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }
Copy the code

Continue to combine code and see RuntimeInit# applicationInit is how to realize the reflection to create “com. Android. Server. SystemServer” class objects and perform its main function:

/*frameworks/base/core/java/com/android/internal/os/RuntimeInit.java*/
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader){...return findStaticMain(args.startClass, args.startArgs, classLoader);
}

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader){ Class<? > cl;try {
            / / 1. By reflecting load build "com. Android. Server. SystemServer" class object
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            / / 2. The access for "com. Android. Server. SystemServer" of the main method
            m = cl.getMethod("main".new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on "+ className, ex); }.../* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */
        // 3. Execute main by throwing an exception and clear the call stack
        return new MethodAndArgsCaller(m, argv);
    }
    
    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                Call main via reflection
                mMethod.invoke(null.new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw newRuntimeException(ex); }}}Copy the code

Can see from the above analysis, the process of system_server after creation, through the reflection to create “com. Android. Server. SystemServer” entrance class objects and perform its main method, we continue to look down the code to simplify the process:

/*frameworks/base/services/java/com/android/server/SystemServer.java*/
public static void main(String[] args) {
        new SystemServer().run();
}

private void run(){...// 1. Create the main thread Looper
    Looper.prepareMainLooper();
    // 2. Create a system Context
    createSystemContext();
    // 3. Create SystemServiceManager to create, start, and manage the life cycle of subsequent system services (such as AMS and WMS)
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    // 4. The service is started in 3 batches according to priority:
    try {
        t.traceBegin("StartServices");
        // Start boot services, such as AMS, PMS, etc
        startBootstrapServices(t);
        // Start the core service
        startCoreServices(t);
         // Start other services
        startOtherServices(t);
     } catch (Throwable ex) {
        Slog.e("System"."* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        Slog.e("System"."************ Failure starting system services", ex);
        throw ex;
     } finally {
        t.traceEnd(); // StartServices
     }
     // 5. Start looper
     Looper.loop();
}
Copy the code

To summarize the process, after the system_server process is created, it does several things:

  1. Binder thread pool to start the process

  2. Create a SystemServiceManager manager for creating, starting, and life cycle management of subsequent system services (such as AMS and WMS).

  3. Use SystemServiceManager to start system services according to their priorities.

  4. Create and start the loop for the main thread of the process.

4. Start the application Launcher

Let’s look at the process of starting the SYSTEM service after the system_server process is created. Take the AMS service as an example, the related simplified code flow is as follows:

/*frameworks/base/services/java/com/android/server/SystemServer.java*/
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t){... t.traceBegin("StartActivityManager");
        SystemServiceManager starts the AMS serviceActivityTaskManagerService atm = mSystemServiceManager.startService( ActivityTaskManagerService.Lifecycle.class).getService(); mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mWindowManagerGlobalLock = atm.getGlobalLock(); t.traceEnd(); . } privatevoid startOtherServices(@NonNull TimingsTraceAndSlog t){...// We now tell the activity manager it is okay to run third party
    // code. It will call back into us once it has gotten to the state
    // where third party code can really run (but before it has actually
    // started launching the initial applications), for us to complete our
    // initialization.
    // 2. From here you can start the three-party APP (such as Launcher)
     mActivityManagerService.systemReady(() -> {
            ...
        }, t);
}
Copy the code

MActivityManagerService# systemReady is used to start the application Launcher.

/*frameworks/base/services/java/com/android/server/am/ActivitymanagerService.java*/
public void systemReady(final Runnable goingCallback, TimingsTraceAndSlog t){...if (bootingSystemUser) {
        t.traceBegin("startHomeOnAllDisplays");
        // Since Android supports multiple users and multiple displays, call Starthome AllDisplays to start the Home Activity on each display
        mAtmInternal.startHomeOnAllDisplays(currentUserId,"systemReady"); t.traceEnd(); }}Copy the code

StartHomeOnAllDisplays will call startHomeActivity to start the application Launcher with CATEGORY_HOME type after multiple calls.

/*frameworks/base/services/java/com/android/server/wm/RootWindowContainer.java*/
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
       boolean allowinstrumenting, boolean fromHomeKey){...// Finally call startHomeActivity to start the application Launcher with CATEGORY_HOME
     mService.startActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea);
     return true;
}
Copy the code

5. Debug suggestions

If your phone starts up slowly, how can we locate the cause of the problem? Here are some debugging suggestions:

5.1 Locating Faults Based on the System log

Restart the phone and use the following ADB command to capture related logs when the phone is turned on:

adb shell “logcat -b events |grep “boot_p””

06-03 09:43:19.554   730   730 I boot_progress_start: 4274 // Indicates that the system kernel has been started, and the first user-space process init has started, which takes 4274ms
06-03 09:43:19.768   730   730 I boot_progress_preload_start: 4487 // Indicates the zygote process starts preloading resources
06-03 09:43:20.669   730   730 I boot_progress_preload_end: 5389 // Indicates that zygote preload is complete
06-03 09:43:21.082  1196  1196 I boot_progress_system_run: 5802 // Indicates that the system_server process is started
06-03 09:43:22.186  1196  1196 I boot_progress_pms_start: 6905 // Indicates that the system PKMS service starts and scans for installed applications
06-03 09:43:22.430  1196  1196 I boot_progress_pms_system_scan_start: 7150
06-03 09:43:22.757  1196  1196 I boot_progress_pms_data_scan_start: 7477
06-03 09:43:23.033  1196  1196 I boot_progress_pms_scan_end: 7753
06-03 09:43:23.185  1196  1196 I boot_progress_pms_ready: 7905// // indicates that the PKMS service scanning is complete
06-03 09:43:24.133  1196  1196 I boot_progress_ams_ready: 8853 // Indicates that AMS is in systemReady state and can start the Home Activity
06-03 09:43:25.468  1196  1523 I boot_progress_enable_screen: 10187 // It indicates that the frequency lock interface has been lit up and displayed, and the whole boot is completed, which takes 10187ms
Copy the code

5.2 Use the BootChart performance analysis tool to locate problems

Bootchart is an open source software tool for analyzing the performance of Linux startup process. It automatically collects information such as CPU usage, disk throughput, and process during the system startup process, and displays the analysis results in a graphical way, which can be used as a guide to optimize the system startup process. With the realization of the bootchart in Android source, path in the system/core/init/bootchart CPP. For details, see the following: blog.csdn.net/qq_19923217…

6. Summary

Finally, a diagram is used to summarize the core startup process of Android system:

7. Refer to the article

Graphic | Android start juejin. Cn/post / 688478…