MTK system startup process

MTK system startup process

boot rom -> preloader ->lk ->kernel ->Native -> Android

1. Boot rom: When the system is turned on, the first thing to be executed is the bootrom solidified inside the chip. Its main functions are
a. Initializing ISRAM and EMMC
. b. When the system is completely wiped, USB will also be configured to simulate the USB port to download the image. .
c. Load the preloader from EMMC to ISRAM for execution.

2. Preloader : Mainly completes the initialization of platform basic equipment, such as DDR and other hardware, downloads the handshake connection, loads lk into DDR, and jumps to lk

3. Lk : Open MMU, accelerate lk execution, display log and charging related, extract boot.img from the boot partition in emmc and decompress it, load the root file system and linux kernel to Dram, complete the preparation work before the kernel and pull up the kernel (start_kernel).

4. Kernel : initialize basic functions of the Linux operating system such as scheduling, memory management, io, and interrupts, identify OTBO, create the init process, complete module initialization, and execute the init main program .

5. Native : Start key system processes init, void, surfaceflinger, etc.

The role of the init process is roughly divided into three parts:

1. Create a backup node, mount and file system,

2. Enable selinux security policy, initialize resource files, start attribute services, etc.;

3. Parse the initrc file;

6. Android: init fork the zygote process, and then zygote creates all Android application processes

The basic flow chart is as follows:

Check the properties to see if it is powered on for the first time.

persist.sys.device_provisionedWhether the boot wizard is completed?

persist.sys.device_first_boot is the first time to boot

1. preloader (assembly/C)

1.1 Function

1. Complete the initialization of platform basic equipment, such as DDR and other hardware

2. Handshake with flashtoolUSB, download related detection & sec boot detection;

3. Load lk into DRAM

4. Jump to Ik

1.2 Entry code

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mtXXXX/src/init/init.s

init.s: initialize registers, clear bss segment, initialize stack, set CPSR, switch to SVC mode, disable interrupts; jump to main after completing the above basic initialization

  setup_stk :
      /* setup stack */
      LDR r0, stack
      LDR r1, stacksz
  
      /* buffer overflow detect pattern */
      LDR r2, =0xDEADBEFF
      STR r2, [r0]
  
      LDR r1, [r1]
      SUB r1, r1, #0x04
      ADD r1, r0, r1
  
      MOV sp, r1
  
  entry :
      LDR r0, =bldr_args_addr
      B   main
  
  .globl jump

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mtXXXX/src/core/main.c

static void bldr_pre_process(void) 
{ 
    int isLocked = 0; 
    int tempnoboot = 0; 
    uint32_t ret = 0; 
	...... 
	//Initialize timer/pll/gpio/uart/WDT/storage/PMIC 
    platform_pre_init(); 

    pal_log_info( "\n%s Build Time: %s\n", MOD, BUILD_TIME); 

	...... 

    /* hardware initialization */ 
	//Initialize RTC/PM/batter/DDR/storage 
    platform_init(); 
    tempnoboot = oplus_bq28z610_temp (); 
    no_boot_log_to_storage(tempnoboot); 
	...... 
} 
 void main(u32 *arg) 
 { 
     struct bldr_command_handler handler; 
     u32 jump_addr, jump_arg; 
...... 
	 //Initialize the platform environment
     bldr_pre_process(); 
 
......... 
 
     BOOTING_TIME_PROFILING_LOG("before bldr_handshake"); 
	 //Handshake connection with the download tool 
     bldr_handshake(&handler); 
     BOOTING_TIME_PROFILING_LOG("bldr_handshake"); 
 
	 //Initialize the security environment 
     trustzone_pre_init(); 
     BOOTING_TIME_PROFILING_LOG(" trustzone pre init"); 
 #endif 
 
 #if !(CFG_BYPASS_LOAD_IMG_FORCE_ATF) 
     /* Do not load ATF, lk, load by JTAG */ 
	 //Load LK image to DRAM 
     if (0 != bldr_load_images(&jump_addr)) { 
         pal_log_err("% s Second Bootloader Load Failed\n", MOD); 
 #if !CFG_BYPASS_EMI 
         goto error; 
 #endif //SLT 
	 //Complete the remaining initialization of the preloader, mainly initializing the battery 
     bldr_post_process(); 
	....... 
	 //Jump to lk
     bldr_jump64(jump_addr, jump_arg, sizeof(boot_arg_t));
	.......
 }

bldr_pre_process initializes the platform environment

platform_pre_init: initialize timer/pll/gpio/uart/WDT/storage/PMIC

platform_init: initialize RTC/PM/batter/DDR/storage

bldr_handshake Handshake connection with download tool

trustzone_pre_init security environment initialization

bldr_load_images loads LK images to DRAM

bldr_post_process completes the remaining initialization of the preloader, mainly initializing the battery

bldr_jump64 jump to lk

2. LK (assembly/C)

2.1 Function

1. Open MMU, enable I/D-cache, accelerate lk execution, display logo and charging related

·2. Remove bootimg from the boot partition in emmc, decompress it, and load the root file system (ramdisk) and linux kernel to DRAM:

3. Parse dtb and write to the designated area of ​​DRAM:

4. Close MMU, irg /fg, close ID-cache, and pull up kernel (startkemel);

2.2 Entry code:

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/lk/arch/arm/crt0.S

crt0.s: Add TZ symbol, perform abort stack and other initialization operations. Jump to kmain

2.3 kmain

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/lk/kernel/main.c

void kmain(void) 
{ //Initialize the work queue, thread table, initialize 
	thread_init_early() 
	after creating bootstrap thread ; 
	//Initialize MMU, cache 
	arch_early_init(); 
	//Platform initialization. Such as timmer, gpio, pmic, etc., establish the lk basic operating environment 
	platform_early_init(); 
....... 
 #if (!ENABLE_NANDWRITE) 
 	// create a thread to complete system initialization 
 	dprintf(SPEW, "creating bootstrap completion thread\n "); 
	//thread_bs2: Create a bootstrap2 thread to complete subsequent initialization and load the app bootstrap2 
 	thread_t *thread_bs2 = thread_create("bootstrap2", &bootstrap2, NULL, 
 		DEFAULT_PRIORITY, DEFAULT_STACK_SIZE); 
... 
 }


 
 

1. Initialize the threads, linked lists and related queues required for system tasks.
2. Initialize the hardware platform and build the lk basic operating environment
3. Initialize the timer, etc.
4. Create a new thread bootstrap2 and execute it. The current thread is placed in idle state

2.4 bootstrap2

static int bootstrap2(void *arg)
{
    dprintf(SPEW, "top of bootstrap2()\n");

    print_stack_of_current_thread();

    arch_init();

    // XXX put this somewhere else
#if WITH_LIB_BIO
    bio_init();
#endif
#if WITH_LIB_FS
    fs_init();
#endif
    // Allocate LK memory from mb, free before jump to kernel
    mboot_allocate_lk_scratch_from_mblock();

    // initialize the rest of the platform
    dprintf(SPEW, "initializing platform\n");
    platform_init();

    // initialize the target
    dprintf(SPEW, "initializing target\n");
    target_init();

    dprintf(SPEW, "calling apps_init()\n");
    apps_init();

    return 0;
}

bootstrap2 thread main function: initialize bio, fs, platform, app

app_init initializes and runs apps one by one

mt_boot executes the subsequent startup process and finally loads the kernel app

3. Kernel (assembly/C)

3.1 Function

Initialize basic functions of the Linux operating system such as scheduling, memory management, IO, interrupts, identify DTBO, create the init process, complete module initialization, and execute the init main program

3.2 Entry code

/MTXXXX_13_Master/vnd/kernel/kernel-5.10/arch/arm64/kernel/head.S

MMU, CPU, page table, Cache, etc. are initialized and jump to start_kernel

3.3 start_kernel

/MTXXXX_13_Master/vnd/kernel/kernel-5.10/init/main.c

After a series of basic initialization is completed, rest_init->kernel_init creates the init process and searches for the init executable file in /sbin/etc/bin in sequence

3.4 DTBO identification process

start_kernel->setup_arch->unflatten_device_tree->unflatten_device_tree->unflatten_dt_nodes

Traverse each node in unflatten_dt_nodes, call populate_node on each node, and convert the information of each node into a device_node structure;

unflatten_dt_alloc creates device_node structure

populate_propertites creates a property structure and adds the device_node attribute to it

3.5 platform bus initialization process

do_basic_setup->driver_init

devices_init: Create two device root nodes /sys/devices /sys/dev and create /sys/dev/block /sys/dev/char

buses_init: Create the /sys/bus bus root node

platform_bus_init

Register the platform_bus device and create the /sys/devices/plaform node. This node is the root node of all platform devices.

Register the platform_bus_type bus type and create the /sys/bus/platfrom node. This node is the bus type root node of all platform devices.

3.6 Add devices from the device tree to platform devices:

Entry function

/MTXXXX_13_Master/vnd/kernel-5.10/drivers/of/platform.c

Add this function to the kernel initialization function set through arch_initcall_sync

Select the appropriate device to join the platform bus through the of_platform_default_populate->of_plattform_populate->platform_bus_create call process

Finally, add the device to platform devices through of_plaform_device_create_pdata->of_device_add

4. Native (C/C++)

4.1 Function

Start the system key processes init, void, surfaceflinger

4.2 init entry code

/MTXXXX_13_Master/sys/system/core/init/main.cpp

int main(int argc, char** argv) {
......

    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

            return SubcontextMain(argc, argv, &function_map);
        }

        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }
    //init第一阶段
    return FirstStageMain(argc, argv);
}

4.3 The first stage of init FirstStageMain

/MTXXXX_13_Master/sys/system/core/init/first_stage_main.cpp

1. Create system directories and mount corresponding partitions

2. Initialize the init phase log to kernel log

3. Load SElinux security policy

// system/core/init/first_stage_init.cpp
int FirstStageMain(int argc, char** argv){
    if(REBOOT_BOOTLOADER_ON_PANIC){
        InstallRebootSignalHandlers();
    }
    boot_clock::time_point start_time = boot_clock::now();
    std::vector<std::pair<std::string, int>> errors;
#define CHECKCALL(x) \
    if (x != 0) errors.emplace_back(#x " failed", errno);
    umask(0);
    // 创建于挂载相关文件系统
    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"));
    CHECKCALL(mkdir("/dev/pts", 0755));
    CHECKCALL(mkdir("/dev/socket", 0755));
    CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
#define MAKE_STR(x) __STRING(x)
    CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
#undef MAKE_STR
    // 原始命令不可暴露给没有特权的进程
    CHECKCALL(chmod("/proc/cmdline", 0440));
    gid_t groups[] = {AID_READPROC};
    CHECKCALL(setgroups(arraysize(groups), groups));
    CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
    CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
    // tmpfs已经挂载在/dev下,并且已生成/dev/kmsg,故可以与外界通信
    // 初始化日志系统
    InitKernelLogging(argv);
    // 进入下一步
    const char* path = "/system/bin/init";
    const char* args[] = {path, "selinux_setup", nullptr};
    execv(path, const_cast<char**>(args));
 
    // 只有在错误发生的情况下execv()函数才会返回
    PLOG(FATAL) << "execv(\"" << path << "\") failed";
 
    return 1;
}

4.4 Second stage of init SecondStageMain

/MTXXXX_13_Master/sys/system/core/init/init.cpp

1. Initialize the property system and read property settings from the specified location: -->Propertyinit()

2. Mount apex/partition-->MountExtraFilesystem s ()

3. SElinux second stage-->SelinuxRestoreContext():

4. Start the property service to add, modify, and obtain properties-->StartPropertyService ()

5. Initialize file context-->InitializeSubcontext()

6. Add am and sm to the collection for subsequent execution in order --> LoadBootscripts (am, sm)

7. Execute init.rc

//  system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {
    SetStdioToDevNull(argv);
    // 初始化本阶段内核日志
    InitKernelLogging(argv);
    //  系统属性初始化
    property_init();
    //  建立 Epoll
    Epoll epoll;
    //  注册信号处理
    InstallSignalFdHandler(&epoll);
    //  加载默认的系统属性
    property_load_boot_defaults(load_debug_prop);
    //  启动属性服务
    StartPropertyService(&epoll);
       subcontexts = InitializeSubcontexts();
    //加载系统启动脚本"/init.rc"
       ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();
    LoadBootScripts(am, sm);
    
       // 触发early-init,,init,late-init流程
    am.QueueEventTrigger("early-init");
    am.QueueEventTrigger("init");
    am.QueueBuiltinAction(InitBinder, "InitBinder");
    am.QueueEventTrigger("late-init");
    
    //解析启动脚本
    while (true) {
        //  执行 Action
        am.ExecuteOneCommand();
        //  还有就是重启死掉的子进程
        auto next_process_action_time = HandleProcessActions();
    }
}

4.5 initrc syntax: Android startup script-specific syntax

Four elements: Action, Command, Service, Option

4.5.1 Action

It consists of a set of commands and a trigger. The trigger statement starts with on. The condition after on determines the timing of execution. When some conditions meet the conditions of the trigger, the command defined in the Action will be added to the command queue to be executed. the tail of the command (if this set of commands is already in the queue, it will not be added again).

Commonly used triggers are as follows:

  1. early-init is triggered in the early stage of initialization
  2. late-init is triggered during the late initialization phase
  3. init is triggered during the initialization phase
  4. late-init is triggered during the late initialization phase
  5. boot/charger Triggered when the system starts/charges
  6. property:<key>=<value> Triggered when the property value meets the conditions, such as: on property:ro.debuggable=1
  7. fs triggers when mounting mtd partition
  8. boot triggers basic network initialization, memory management, etc.
  9. post-fs triggers when the access permissions of the system directory are changed.
  10. device-added-<path> Triggered when a device node is added
  11. device-removed-<path> Triggered when the device node is deleted
  12. service-exited-<name> is triggered when a specific service (service) exits

on earty-init creates a file directory, sets restrictions on the process (nice, fd) and starts ueventd

on init creates a file directory, assigns user groups to each node, and starts services such as logd, Imkd, servicemanager, etc.

on late-init

on early-fs: start voId

on fs: Mount file directory

on postfs: Mount the file system rootfs (remount).

on late-fs: stores HALs required before encryption and unlocking such as (keyasten)

on post-fs-data: Mount data, start apexd, initialize the first user, start fuse,

zygote-start: Need to start zygote.netdzygote-secondnary together with the encryption status

on boot: start hal, start core service

4.5.2 command

Commonly used commands:

1).import <filename>          
  导入init.XX.rc、xxx.conf等文件  
   Parse an init config file, extending the current configuration.

2).chmod <octal-mode> <path>  
   Change file access permissions.

3).chown <owner> <group> <path>  
   Change file owner and group.  
    
4).chdir <directory>  
   Change working directory.  
    
5).chroot <directory>   
  改变进程根目录  
    
6).insmod <path>     
  加载XX.ko驱动模块

7).start <service>  
   Start a service running if it is not already running.

8).stop <service>  
   Stop a service from running if it is currently running.

9).class_start <serviceclass>  
   Start all services of the specified class if they are not already running. 

10).class_stop <serviceclass>   
   Stop all services of the specified class if they are currently running.   
       
   class_reset <serviceclass> //Restart all services under class   
       
11).setprop <name> <value>     
   Set system property <name> to <value>.   
   You can view the property value of the current system through the getprop command   
    
12). export <name> <value>          
  Set a global environment variable. This variable value can be accessed by all processes. (Global, always exists)   
  The value of this environment variable can be obtained in the code through the value = getenv("name") interface   
    
13).mkdir <path> [mode] [owner] [group]   
   creates a directory, and the following items are defaulted The values ​​are mode, owner, group: 0755 root root 

14).trigger <event>   
   Trigger an action.  Used to queue an action from another action.  
   exec <path> [ <argument> ]* Execute the Program specified by <path> and can have execution parameters.  
   exec executes an executable file within the calling process and blocks the current process until the execution is completed.  
 
   It is best to avoid using the exec command like those builtin commands, otherwise it will easily cause blocking or stuck (maybe there should be a timeout?) 

16) .ifup <interface>   
   starts a certain network interface and makes it in the up state, which can be viewed through netcfg. ifup eth0 is equivalent to netcfg eth0 up and has the same function.   
    
17).hostname <name>   
   sets the host name of the device. Generally, the default setting is localhost. , can be modified through hostname new_name in the terminal 

18).domainname <name>   
   Set the network domain name localdomain 

19).mount <type> <device> <dir> [ <mountoption> ]* 
    Mount the device to the dir directory, file system Type is type.  
   <mountoption>s include "ro", "rw", "remount", "noatime", "nosuid"..., please check [linux](http://lib.csdn.  
    

21).setrlimit <resource> <cur> <max>   
  setrlimit <resource> <cur> <max> Set the resource upper limit of this service process. (Usage example??)

22).symlink <target> <path>      
   path links to ---》target; create a symbolic link 

23).sysclktz <mins_west_of_gmt>     
  Set the system time zone (0 if system clock ticks in GMT) 

24).wait <path> [ <timeout> ]   
 polls to find whether the given file path exists. If it is found or times out, it will return. The default timeout is 5 seconds. (Usage example???) 

25).write <path> <string> [ <string> ]*   
   Open a file and use the write command to write one or more strings

4.5.3 service

Services is a program that starts with service and is started by the init process. It usually runs in another init sub-process, so before starting the service, you need to determine whether the corresponding executable file exists. The child process generated by init is defined in the rc file. Each service will generate a child process through fork when it is started. Services have the form:

Services refer to those programs that need to be started when the system is initialized or automatically restarted when it exits.

Its grammatical structure is as follows:

1.  service <name> <pathname> [ <argument> ]* 
2.   <option> 
3.   <option> 
4.   ...

pathname: must have executable permissions. Service name: cannot be repeated in all rc files.

4.5.4 option option

  • class <class_name>
    indicates that the service belongs to the class class_name. The default service belongs to the "default" class. Services under the same class can be started or stopped together.
  • Disabled
    means that when the class where the service is located is started, the service will not start automatically.
    You must use start server_name or property_set("ctl.start", server_name); to start.
  • Oneshot
    will not restart after the service exits. If this option is not added, the service will restart after exiting by default.
  • user <username>
    declares the user name of the service before executing the service. The default value should be the root user.
  • group <groupname> [ <groupname> ]*
    Before executing the service, declare the group name to which the service belongs. You can declare it to belong to multiple groups at one time.
    When declaring multiple groups, except for the first group name, the others are the supplementary group names of the service (call the interface setgroups()).
  • When the onrestart + command
    service is restarted, the command after onrestart will be executed.
    eg: onrestart restart media restarts the service named media.
  • setenv <name> <value>
    Sets the value of the environment variable name to value in the current service process.
    Note: The environment variable defined by setenv only takes effect within this process. If you exit the process or close the corresponding program running window, the environment variable will be invalid.) The value of this environment variable can be obtained through the getenv("name") interface in the
    program
    setenv The difference with export:
    setenv csh, it takes effect in this process. After exiting, the variables are invalid.
    export bash, it takes effect globally and always exists.
    Format:
    export key=value
    setenv key value
  • critical
    declares a critical service. If the service exits four times within four minutes, the device enters recovery mode
  • socket <name> <type> <perm> [ <user> [ <group> ] ]
    Create a unix domain socket named /dev/socket/<name> and pass its handle fd to this service process
    <type> Must be "dgram", "stream" or "seqpacket".User and group default to 0, which is root.
  • seclablel changes the security context before executing the service

5. Android (JAVA)

init fork the zygote process, and then zygote creates all Android application processes.

5.1 ZygoteInit

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) {
       //1、创建ZygoteServer
        ZygoteServer zygoteServer = new ZygoteServer();
      .......
        try {
             .......
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
           // 2、解析app_main.cpp传来的参数
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[I]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }
            //3、创建一个Server端的Socket
            zygoteServer.registerServerSocket(socketName);
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) { 
                bootTimingsTraceLog.traceBegin("ZygotePreload"); 
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, 
                    SystemClock.uptimeMillis()); 
               //4. Load the resources and classes of the process 
                preload(bootTimingsTraceLog); 
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, 
                    SystemClock .uptimeMillis()); 
                bootTimingsTraceLog.traceEnd(); // ZygotePreload 
            } else { 
                Zygote.resetNicePriority(); 
            } 
              ........
            if (startSystemServer) { 
                //5. Start the SystemServer process 
                startSystemServer(abiList, socketName, zygoteServer); 
            } 

            Log.i(TAG, "Accepting command socket connections"); 
           //6. Start an infinite loop to listen for messages from the Client 
            zygoteServer.runSelectLoop(abiList); 
           / /7. Close the SystemServer's Socket 
            zygoteServer.closeServerSocket(); 
        } catch (Zygote.MethodAndArgsCaller caller) { 
           //8. Catch this exception here and call the run method of MethodAndArgsCaller. 
            caller.run(); 
        } catch (Throwable ex) { 
            Log.e(TAG, "System zygote died with exception", ex); 
            zygoteServer.closeServerSocket(); 
            throw ex; 
        } 
    }

5.2 Zygote process

1. Create a java virtual machine

2. Register native methods for the java virtual machine

3. Call the main method of the java class in com.android.initernal.os.ZygoteInit

4. Load Zygotelnit class

5. Register Zygote socker

6. Load preload class

7. Load the preload resource file

8. Call Zygote::forkSystemServer, fork a new process, call the main method of SystemServer, and start the SystemServer process.

1. Parse the parameters in init.zygote.rc, create AppRuntime and call the AppRuntime.start() method

2. Call the startVM() method of AndroidRuntime to create a virtual machine, and then call startReg() to register the JNI function

3. Call Zygotelnitmain0) through JNI and enter the Java world for the first time

4.registerZygoteSocket() establishes a socket channel, and zygote serves as the communication server to respond to client requests.

5.preload() preloads common classes, drawable and color resources, openGL, shared libraries and WebView to improve app startup efficiency

6. Through startSystemServer(), fork's powerful helper system_server process

7. Call runSelectLoop0(), wake up immediately and perform the corresponding work when receiving a request to create a new process.

③Zygote function

CreateSystemServer

Incubate application processes

5.3 Related processes

init process: When Nessot creates the init process, it executes init. The final stage of the init process parses the init.rc script and starts various process services. The most important one is to start the zygote process.

zygote process: The zygote process is the first java process started by the system and runs in the framework layer. This process is mainly responsible for creating all applications including systemserver and creating a virtual machine operating environment.

systemsserver process: Start Binder thread pool and SystemServiceNanager;

systemServiceManager is mainly responsible for creating, starting and life-cycle management of system services, and will start various system services. (AMS, the core service in android, is started in the SystemServer process)

Launcher process: The launcher process is the last step in the startup of the Android system. It is mainly responsible for displaying installed applications on the interface.

 5.4 SystemServer startup related code is as follows

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

private void run() {
    try {
        Looper.prepareMainLooper();
        // 初始化本地服务
        System.loadLibrary("android_servers");
         // 初始化系统上下文
        createSystemContext();
        // 创建SystemServiceManager
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setStartInfo(mRuntimeRestart,
                mRuntimeStartElapsedTime, mRuntimeStartUptime);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // 构建线程池,以便并行执行一些初始化任务
        SystemServerInitThreadPool.get();
    } finally {
        traceEnd();  // InitBeforeStartServices
    }
 
    // 开启服务
    try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices();// 启动引导服务
        startCoreServices();// 启动核心服务
        startOtherServices();// 启动其他服务
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        traceEnd();
    }
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

As you can see, the most important job of SystemServer is to start all services by executing three methods

  • startBootstrapServices();
  • startCoreServices();
  • startOtherServices();

Corresponding to boot services, core services and other services respectively:

  • Bootstrap services: Such services include Installer, ActivityManagerService
    PowerManagerService, DisplayManagerService, PackageManagerService, UserManagerService, etc.
  • Core services: Such services include LightsService, BatteryService, UsageStatsServtce,
    WebViewUpdateService, etc.
  • Other services: All other services

SystemUI will be started in the startOtherServices() method, and then SystemServer will notify AMS that the system is ready. At this time, AMS starts the desktop and sends a BOOT_COMPLETED broadcast. At this point, the system level startup process ends.

5.5 Google official boot optimization information

https://source.android.com/devices/tech/perf/boot-times

Guess you like

Origin blog.csdn.net/weixin_47465999/article/details/131932957