(三)Android系统启动流程

(三)Android系统启动流程



一、启动流程概述

大概流程如下:

在这里插入图片描述

1.启动电源及系统启动

按下电源开始,引导程序芯片开始从预定义(rom固件)开始执行,加载RAM引导程序。

2.启动bootloader

引导程序是Android系统的一个小程序,是开始启动的第一个程序,是针对特定的主板或芯片决定的。常用的引导程序有redboot、uboot、qi bootloader等。

3.加载内核

Android内核与桌面linux内核启动的方式差不多。 内核启动时, 设置缓存、 被保护存储器、 计划列表,加载驱动。 当内核完成系统设置, 它首先在系统文件中寻找” init” 文件, 然后启动root进程或者系统的第 一个进程。

4.启动init进程

init进程是Linux系统中用户空间的第一个进程, 进程号固定为1。 Kernel启动后, 在用户空间启动init进程, 并调用init中的main()方法执行init进程的职责。

5.启动zygote进程

Init 进程和一些重要的守护进程启动完成之后,系统启动 Zygote 进程。Zygote 进程启动后,首先初始化一个 Dalvik VM实例,然后为它加载资源与系统共享库,并开启 Socket 监听服务,当收到创建Dalvik VM 实例请求时,会通过COW(copy on write)技术最大程度地复用自己,生成一个新的Dalvik VM 实例。Dalvik VM 实例的创建方法基于 linux 系统的 fork 原理。

6.启动本地服务

在 Zygote 进程启动完成之后,Init 进程会启动 Runtime 进程。然后 Runtime 进程会向 Zygote进程发送启动系统服务(System Service)的请求。System Service 会首先启动两个本地服务(由C或C++编写的native服务),Surface Flinger 和Audio Flinger,这两个本地系统服务向服务管理器注册成为 IPC 服务对象,以便在需要它们的时候很容易查找到。然后 SystemService 会启动一些 Android 系统管理服务,包括硬件服务和系统框架核心平台服务,并注册它们成为 IPC 服务对象。

7.Launcher App启动

当 SystemService 加载了所有的系统服务后就相当于系统启动完成了,它会向所有服务发送一个开机完成广播。AMS收到开机广播后,然后在系统中查找具有<category android:name = “android.intent.category.HOME”/>属性的Activity,并启动。

二、init进程

1.init进程入口

该流程分析如下:

1.挂载文件:通过设置umask值,屏蔽一些权限后,开始挂载和创建所需的文件;
2.属性服务:通过property_init()属性服务初始化,调用start_property_service()启动属性服务;
3.子进程的处理函数: signal_handler_init()主要作用是防止出现僵尸进程,子进程在暂停和终止后,会发出SIGCHLD的信号,signal_handler_init()接收到该信号后,会对该进程进行回收处理,防止占用系统进程资源;
4.解析init.rc配置:在8.0中对init.rc文件进行了拆分,可查看system\core\rootdir目录,包括:

  • init.zygote32.rc:Zygote对应的执行程序是app_process(纯32位模式);
  • init.zygote64.rc:Zygote对应的执行程序是app_process64(纯64位模式);
  • init.zygote32_64.rc:启动两个Zygote进程( zygote 和 zygote_secondary),对应的执行程序是app_process32(主模式)和app_process64;
  • init.zygote64_32.rc:启动两个Zygote进程( zygote 和 zygote_secondary),对应的执行程序是app_process64(主模式)和app_process32。

代码如下(示例):

\system\core\init\init.cpp main()
//init的main函数有两个其它入口, 一是参数中有ueventd, 进入ueventd_main,二是参数中有watchdogd, 进入watchdogd_main
int main(int argc, char** argv) {
    //表示true时, 也就执行ueventd_main,ueventd主要是负责设备节点的创建、 权限设定等一些列工作
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    //watchdogd俗称看门狗, 用于系统出问题时重启系统
    if (!strcmp(basename(argv[0]), "watchdogd")) {
        return watchdogd_main(argc, argv);
    }

    if (argc > 1 && !strcmp(argv[1], "subcontext")) {
        InitKernelLogging(argv);
        const BuiltinFunctionMap function_map;
        return SubcontextMain(argc, argv, &function_map);
    }

    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();//初始化重启系统的处理信号, 内部通过sigaction 注册信号, 当监听到该信号时重启系统
    }

    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);

    //init的main方法会执行两次, 由is_first_stage控制,first_stage就是第一阶段要做的事
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();

        // Clear the umask.
        umask(0);//清空文件权限

        clearenv();
        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.
        //mount是用来挂载文件系统的, mount属于Linux系统调用
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);//创建目录, 第一个参数是目录路径, 第二个是读写权限
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        #define MAKE_STR(x) __STRING(x)
        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
        // Don't expose the raw commandline to unprivileged processes.
        chmod("/proc/cmdline", 0440);
        gid_t groups[] = { AID_READPROC };
        setgroups(arraysize(groups), groups);// 用来将list 数组中所标明的组加入到目前进程的组设置中
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
        //mknod用于创建Linux中的设备文件
        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));

        if constexpr (WORLD_WRITABLE_KMSG) {
            mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11));
        }

        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));

        // Mount staging areas for devices managed by vold
        // See storage config details at http://source.android.com/devices/storage/
        mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
              "mode=0755,uid=0,gid=1000");
        // /mnt/vendor is used to mount vendor-specific partitions that can not be
        // part of the vendor partition, e.g. because they are mounted read-write.
        mkdir("/mnt/vendor", 0755);

        // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
        // talk to the outside world...
        InitKernelLogging(argv);//将标准输入输出重定向到"/sys/fs/selinux/null"

        LOG(INFO) << "init first stage started!";

        if (!DoFirstStageMount()) {
            LOG(FATAL) << "Failed to mount required partitions early ...";
        }
       //Avb即Android Verfied boot,功能包括Secure Boot, verfying boot 和 dm- verity,
       //原理都是对二进制文件进行签名, 在系统启动时进行认证, 确保系统运行的是合法的二进制镜像文件。
       //其中认证的范围涵盖: bootloader, boot.img, system.img
        SetInitAvbVersionInRecovery();//在刷机模式下初始化avb的版本,不是刷机模式 直接跳过

        // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
        global_seccomp();

        // Set up SELinux, loading the SELinux policy.
        SelinuxSetupKernelLogging();
        SelinuxInitialize();

        // We're in the kernel domain, so re-exec init to transition to the init domain now
        // that the SELinux policy has been loaded.
        /*
         * 1.这句英文大概意思是, 我们执行第一遍时是在kernel domain, 所以要重新执行init文件, 切换到init domain,
         * 这样SELinux policy才已经加载进来了
         * 2.后面的security_failure函数会调用panic重启系统
         */
        if (selinux_android_restorecon("/init", 0) == -1) {
            PLOG(FATAL) << "restorecon failed of /init failed";
        }

        setenv("INIT_SECOND_STAGE", "true", 1);

        static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
        uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
        setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);

        char* path = argv[0];
        char* args[] = { path, nullptr };
        execv(path, args);//重新执行main方法, 进入第二阶段

        // execv() only returns if an error happened, in which case we
        // panic and never fall through this conditional.
        PLOG(FATAL) << "execv(\"" << path << "\") failed";
    }

    // At this point we're in the second stage of init.
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";

    // Set up a session keyring that all processes will have access to. It
    // will hold things like FBE encryption keys. No process should override
    // its session keyring.
    keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);

    // Indicate that booting is in progress to background fw loaders, etc.
    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));

    property_init();//初始化属性系统, 并从指定文件读取属性
    
    //接下来的一系列操作都是从各个文件读取一些属性, 然后通过property_set设置系统属性
    // If arguments are passed both on the command line and in DT,
    // properties set in DT always have priority over the command-line ones.
    process_kernel_dt();
    process_kernel_cmdline();

    // Propagate the kernel variables to internal variables
    // used by init as well as the current required properties.
    export_kernel_boot_props();

    // Make the time that init started available for bootstat to log.
    property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
    property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));

    // Set libavb version for Framework-only OTA match in Treble build.
    const char* avb_version = getenv("INIT_AVB_VERSION");
    if (avb_version) property_set("ro.boot.avb_version", avb_version);

    // Clean up our environment.
    unsetenv("INIT_SECOND_STAGE");//清空这些环境变量, 因为之前都已经存入到系统属性 中去了
    unsetenv("INIT_STARTED_AT");
    unsetenv("INIT_SELINUX_TOOK");
    unsetenv("INIT_AVB_VERSION");

    // Now set up SELinux for second stage.
    SelinuxSetupKernelLogging();
    SelabelInitialize();
    SelinuxRestoreContext();

    epoll_fd = epoll_create1(EPOLL_CLOEXEC);//创建epoll实例, 并返回epoll的文件描述符
    if (epoll_fd == -1) {
        PLOG(FATAL) << "epoll_create1 failed";
    }

    sigchld_handler_init();//主要是创建handler处理子进程终止信号, 创建一个匿名socket并注册到epoll进行监听

    if (!IsRebootCapable()) {
        // If init does not have the CAP_SYS_BOOT capability, it is running in a container.
        // In that case, receiving SIGTERM will cause the system to shut down.
        InstallSigtermHandler();
    }

    property_load_boot_defaults();//从文件中加载一些属性, 读取usb配置
    export_oem_lock_status();//设置ro.boot.flash.locked 属性
    start_property_service();//开启一个socket监听系统属性的设置
    set_usb_controller();//设置sys.usb.controller 属性

    const BuiltinFunctionMap function_map;
    Action::set_function_map(&function_map);//将function_map存放到Action中作 为成员属性

    subcontexts = InitializeSubcontexts();

    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();

    LoadBootScripts(am, sm);//解析xxx.rc

    // Turning this on and letting the INFO logging be discarded adds 0.2s to
    // Nexus 9 boot time, so it's disabled by default.
    if (false) DumpState();

    am.QueueEventTrigger("early-init");//QueueEventTrigger用于触发Action,这里 触发 earlyinit事件

    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
    am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");//QueueBuiltinAction用于添加Action, 第一个参数是Action要执行的Command,第二个是Trigger
    // ... so that we can start queuing up actions that require stuff from /dev.
    am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
    am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
    am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
    am.QueueBuiltinAction(keychord_init_action, "keychord_init");
    am.QueueBuiltinAction(console_init_action, "console_init");

    // Trigger all the boot actions to get us started.
    am.QueueEventTrigger("init");

    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
    // wasn't ready immediately after wait_for_coldboot_done
    am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");

    // Don't mount filesystems or start core system services in charger mode.
    std::string bootmode = GetProperty("ro.bootmode", "");
    if (bootmode == "charger") {
        am.QueueEventTrigger("charger");
    } else {
        am.QueueEventTrigger("late-init");
    }

    // Run all property triggers based on current state of the properties.
    am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");

    while (true) {
        // By default, sleep until something happens.
        int epoll_timeout_ms = -1; //epoll超时时间, 相当于阻塞时间

        if (do_shutdown && !shutting_down) {
            do_shutdown = false;
            if (HandlePowerctlMessage(shutdown_command)) {
                shutting_down = true;
            }
        }

        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            am.ExecuteOneCommand();//执行一个command
        }
        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            if (!shutting_down) {
                auto next_process_restart_time = RestartProcesses();//重启服务

                // If there's a process that needs restarting, wake up in time for that.
                if (next_process_restart_time) {
                    epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>(
                                           *next_process_restart_time - boot_clock::now())
                                           .count();
                    if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
                }
            }

            // If there's more work to do, wake up again immediately.
            if (am.HasMoreCommands()) epoll_timeout_ms = 0;//当还有命令要执行时, 将epoll_timeout_ms设置为0
        }

        epoll_event ev;
        /*
		 * 1.epoll_wait与epoll_create1、 epoll_ctl是一起使用的
		 * 2.epoll_create1用于创建epoll的文件描述符, epoll_ctl、 epoll_wait都把它创建的fd作为第一个参数传入
 		 * 3.epoll_ctl用于操作epoll, EPOLL_CTL_ADD: 注册新的fd到epfd中,EPOLL_CTL_MOD: 修改已经注册的fd的监听事件,EPOLL_CTL_DEL: 从epfd中删除一个fd;
		 * 4.epoll_wait用于等待事件的产生, epoll_ctl调用EPOLL_CTL_ADD时会传入需要监听什么类型的事件,
 		 * 比如EPOLLIN表示监听fd可读, 当该fd有可读的数据时, 调用epoll_wait经过epoll_timeout_ms时间就会把该事件的信息返回给&ev
		 */
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
        if (nr == -1) {
            PLOG(ERROR) << "epoll_wait failed";
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();//当有event返回时, 取出ev.data.ptr( 之前epoll_ctl注册时的回调函数) , 直接执行
                                        //在signal_handler_init和start_property_service有注册两个fd的监 听, 一个用于监听SIGCHLD(子进程结束信号), 一个用于监听属性设置
        }
    }

    return 0;
}

2.init.rc解析

init.rc是一个非常重要的配置文件, 它是由Android初始化语言( Android Init Language) 编写的脚本, 它主要包含五种类型语句:

  • Action( Action中包含了一系列的Command)
  • Commands( init语言中的命令)
  • Services( 由init进程启动的服务)
  • Options( 对服务进行配置的选项)
  • Import( 引入其他配置文件)

代码如下(init):

on init
    sysclktz 0

    # Mix device-specific information into the entropy pool
    copy /proc/cmdline /dev/urandom
    copy /default.prop /dev/urandom

    symlink /system/bin /bin
    symlink /system/etc /etc

    # Backward compatibility.
    symlink /sys/kernel/debug /d

    # Link /vendor to /system/vendor for devices without a vendor partition.
    symlink /system/vendor /vendor

    # Create energy-aware scheduler tuning nodes
    mkdir /dev/stune
    mount cgroup none /dev/stune nodev noexec nosuid schedtune
    mkdir /dev/stune/foreground
    mkdir /dev/stune/background
    ...

(1)Action

Action: 通过触发器trigger, 即以on开头的语句来决定执行相应的service的时机, 具体有如下时机:

  • on early-init; 在初始化早期阶段触发;
  • on init; 在初始化阶段触发;
  • on late-init; 在初始化晚期阶段触发;
  • on boot/charger: 当系统启动/充电时触发, 还包含其他情况, 此处不一一列举;
  • on property:=: 当属性值满足条件时触发

(2)Service

服务Service, 以 service开头, 由init进程启动, 一般运行在init的一个子进程, 所以启动service前需要判断对应的可执行文件是否存在。 init生成的子进程, 定义在rc文件, 其中每一个service在启动时会通过fork方式生成子进程。
例如: service servicemanager /system/bin/servicemanager代表的是服务名为servicemanager, 服务执行的路径为/system/bin/servicemanager。

(3)Command

下面列举常用的命令

  • class_start <service_class_name>: 启动属于同一个class的所有服务;
  • start <service_name>: 启动指定的服务, 若已启动则跳过;
  • stop <service_name>: 停止正在运行的服务
  • setprop : 设置属性值
  • mkdir : 创建指定目录
  • symlink <sym_link>: 创建连接到的<sym_link>符号链接;
  • write : 向文件path中写入字符串;
  • exec: fork并执行, 会阻塞init进程直到程序完毕;
  • exprot : 设定环境变量;

(4)Options

Options是Service的可选项, 与service配合使用

  • disabled: 不随class自动启动, 只有根据service名才启动;
  • oneshot: service退出后不再重启;
  • user/group: 设置执行服务的用户/用户组, 默认都是root;
  • class: 设置所属的类名, 当所属类启动/退出时, 服务也启动/停止, 默认为
  • default; onrestart:当服务重启时执行相应命令;
  • socket: 创建名为/dev/socket/ 的socket
  • critical: 在规定时间内该service不断重启, 则系统会重启并进入恢复模式
  • default: 意味着disabled=false, oneshot=false, critical=false。

(5)Service解析流程

主要文件:
\system\core\init\init.cpp LoadBootScripts()
\system\core\init\init.cpp CreateParser()//创建解析器
\system\core\init\parser.cpp ParseData()
\system\core\init\service.cpp ParseSection()
\system\core\init\service.cpp ParseLineSection()
\system\core\init\service.cpp EndSection()
\system\core\init\service.cpp AddService()
\system\core\init\builtins.cpp do_class_start()
\system\core\init\service.cpp StartIfNotDisabled()
\system\core\init\service.cpp Start()启动服务

//\system\core\init\init.cpp LoadBootScripts()
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser = CreateParser(action_manager, service_list);//创建解析器

    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}
//\system\core\init\init.cpp CreateParser()
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser;

    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));//service解析
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontexts));
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));

    return parser;
}
//\system\core\init\parser.cpp ParseData()
void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {
    ...
    for (;;) {
        switch (next_token(&state)) {
            case T_EOF:
                end_section();
                return;
            case T_NEWLINE:
                state.line++;
                if (args.empty()) break;
                // If we have a line matching a prefix we recognize, call its callback and unset any
                // current section parsers.  This is meant for /sys/ and /dev/ line entries for
                // uevent.
                for (const auto& [prefix, callback] : line_callbacks_) {
                    if (android::base::StartsWith(args[0], prefix)) {
                        end_section();

                        if (auto result = callback(std::move(args)); !result) {
                            (*parse_errors)++;
                            LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
                        }
                        break;
                    }
                }
                if (section_parsers_.count(args[0])) {
                    end_section();
                    section_parser = section_parsers_[args[0]].get();
                    section_start_line = state.line;
                    if (auto result =
                            section_parser->ParseSection(std::move(args), filename, state.line);
                        !result) {
                        (*parse_errors)++;
                        LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
                        section_parser = nullptr;
                    }
                } else if (section_parser) {
                    if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
                        !result) {
                        (*parse_errors)++;
                        LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
                    }
                }
                args.clear();
                break;
            case T_TEXT:
                args.emplace_back(state.text);
                break;
        }
    }
}
//\system\core\init\service.cpp ParseSection()
Result<Success> ServiceParser::ParseSection(std::vector<std::string>&& args,
                                            const std::string& filename, int line) {
    if (args.size() < 3) {
        return Error() << "services must have a name and a program";
    }

    const std::string& name = args[1];
    if (!IsValidName(name)) {
        return Error() << "invalid service name '" << name << "'";
    }

    Subcontext* restart_action_subcontext = nullptr;
    if (subcontexts_) {
        for (auto& subcontext : *subcontexts_) {
            if (StartsWith(filename, subcontext.path_prefix())) {
                restart_action_subcontext = &subcontext;
                break;
            }
        }
    }

    std::vector<std::string> str_args(args.begin() + 2, args.end());
    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);//构建出一个service对象
    return Success();
}
// \system\core\init\service.cpp ParseLineSection() 
  Result<Success> ServiceParser::ParseLineSection(std::vector<std::string>&&args, int line) {
	 return service_ ? service_->ParseLine(std::move(args)) : Success(); 
  }
// \system\core\init\service.cpp EndSection() 
Result<Success> ServiceParser::EndSection() {
    if (service_) {
        Service* old_service = service_list_->FindService(service_->name());
        if (old_service) {
            if (!service_->is_override()) {
                return Error() << "ignored duplicate definition of service '" << service_->name()
                               << "'";
            }

            service_list_->RemoveService(*old_service);
            old_service = nullptr;
        }

        service_list_->AddService(std::move(service_));
    }

    return Success();
}
// \system\core\init\service.cpp AddService() 
void ServiceList::AddService(std::unique_ptr<Service> service) {
    services_.emplace_back(std::move(service));
}

上面解析完成后, 接下来就是启动Service,这里我们以启动Zygote来分析

// \system\core\rootdir\init.rc L680
 on nonencrypted
  class_start main //class_start是一个命令, 通过do_class_start函数处理
  class_start late_start
// \system\core\init\builtins.cpp do_class_start()
static Result<Success> do_class_start(const BuiltinArguments& args) {
    // Starting a class does not start services which are explicitly disabled.
    // They must  be started individually.
    for (const auto& service : ServiceList::GetInstance()) {
        if (service->classnames().count(args[1])) {
            if (auto result = service->StartIfNotDisabled(); !result) {
                LOG(ERROR) << "Could not start service '" << service->name()
                           << "' as part of class '" << args[1] << "': " << result.error();
            }
        }
    }
    return Success();
}
// \system\core\init\service.cpp StartIfNotDisabled() 
 Result<Success> Service::StartIfNotDisabled() {
 	if (!(flags_ & SVC_DISABLED)) {
	 return Start();
	} else {
	 flags_ |= SVC_DISABLED_START; 7 }
 	return Success();
 }
// \system\core\init\service.cpp Start() 

Result<Success> Service::Start() {
    ...
    //如果已经运行,则不启动。
    if (flags_ & SVC_RUNNING) {
        if ((flags_ & SVC_ONESHOT) && disabled) {
            flags_ |= SVC_RESTART;
        }
        // It is not an error to try to start a service that is already running.
        return Success();
    }

    ...
    //判断对应的服务文件是否存在,不存在则不运行。
    struct stat sb;
    if (stat(args_[0].c_str(), &sb) == -1) {
        flags_ |= SVC_DISABLED;
        return ErrnoError() << "Cannot find '" << args_[0] << "'";
    }

    std::string scon;
    if (!seclabel_.empty()) {
        scon = seclabel_;
    } else {
        auto result = ComputeContextFromExecutable(args_[0]);
        if (!result) {
            return result.error();
        }
        scon = *result;
    }

    LOG(INFO) << "starting service '" << name_ << "'...";

    //如果子进程没有启动,则调用fork启动创建子进程
    pid_t pid = -1;
    if (namespace_flags_) {
        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
    } else {
        pid = fork();
    }

    if (pid == 0) {//当期代码在子进程中运行
        umask(077);
        ...

        //启动service子进程
        if (!ExpandArgsAndExecv(args_)) {
            PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
        }

        _exit(127);
    }
    ...
    return Success();
}

三、Zygote进程

1.zygote概述

java应用程序, 主要基于ART虚拟机, 所有的应用程序apk都属于这类native程序, 也就是利用C或C++语 言开发的程序, 如bootanimation。 所有的Java应用程序进程及系统服务SystemServer进程都由Zygote 进程通过Linux的fork()函数孵化出来的, 这也就是为什么把它称为Zygote的原因, 孵化出无数子进程, 而native程序则由Init程序创建启动。 Zygote进程最初的名字不是“ zygote” 而是“ app_process” , 这个名字是在Android.mk文件中定义的Zgyote是Android中的第一个art虚拟机, 他通过socket的方式与其他进程进行通信。 这里的“ 其他进程”其实主要是系统进程——SystemServer。
Zygote是一个C/S模型, Zygote进程作为服务端, 它主要负责创建Java虚拟机, 加载系统资源, 启
动SystemServer进程, 以及在后续运行过程中启动普通的应用程序, 其他进程作为客户端向它发
出“ 孵化” 请求, 而Zygote接收到这个请求后就“ 孵化” 出一个新的进程。 比如, 当点击Launcher里
的 应用程序图标去启动一个新的应用程序进程时, 这个请求会到达框架层的核心服务
ActivityManagerService中, 当AMS收到这个请求后, 它通过调用Process类发出一个“ 孵化” 子进
程的Socket请求, 而Zygote监听到这个请求后就立刻fork一个新的进程出来。

2.zygote启动过程

Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。
在这里插入图片描述

step 1. app_process.main
/*
* app_process 里面定义了三种应用程序类型:
* 1. Zygote: com.android.internal.os.ZygoteInit
* 2. System Server, 不单独启动, 而是由Zygote启动
* 3. 其他指定类名的Java 程序
*/
//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;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    ...

    //这些Java的应用都是通过 AppRuntime.start( className)开始的
    //其实AppRuntime是AndroidRuntime的子类, 它主要实现了几个回调函数, 而start()方法是实现在AndroidRuntime这个方法类里
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

Step 2. AndroidRuntime.start

这个函数的作用是启动Android系统运行时库
它主要做了三件事情:

  • 一是调用函数startVM启动虚拟机,
  • 二是调用函数startReg注册JNI方法,
  • 三是调用了com.android.internal.os.ZygoteInit类的main函数。
//frameworks/base/core/jni/AndroidRuntime.cpp

/* 
* Start the Android runtime.  This involves starting the virtual machine 
* and calling the "static void main(String[] args)" method in the class 
* named by "className". 
*/  
void AndroidRuntime::start(const char* className, const bool startSystemServer)  
{  
    ......  
  
    char* slashClassName = NULL;  
    char* cp;  
    JNIEnv* env;  
  
    ......  
  
    /* start the virtual machine */  
    if (startVm(&mJavaVM, &env) != 0)  
        goto bail;  
  
    /* 
    * Register android functions. 
    */  
    if (startReg(env) < 0) {  
        LOGE("Unable to register all android natives\n");  
        goto bail;  
    }  
  
    /* 
    * We want to call main() with a String array with arguments in it. 
    * At present we only have one argument, the class name.  Create an 
    * array to hold it. 
    */  
    jclass stringClass;  
    jobjectArray strArray;  
    jstring classNameStr;  
    jstring startSystemServerStr;  
    stringClass = env->FindClass("java/lang/String");  
    assert(stringClass != NULL);  
    strArray = env->NewObjectArray(2, stringClass, NULL);  
    assert(strArray != NULL);  
    classNameStr = env->NewStringUTF(className);  
    assert(classNameStr != NULL);  
    env->SetObjectArrayElement(strArray, 0, classNameStr);  
    startSystemServerStr = env->NewStringUTF(startSystemServer ?  
        "true" : "false");  
    env->SetObjectArrayElement(strArray, 1, startSystemServerStr);  
  
    /* 
    * Start VM.  This thread becomes the main thread of the VM, and will 
    * not return until the VM exits. 
    */  
    jclass startClass;  
    jmethodID startMeth;  
  
    slashClassName = strdup(className);  
    for (cp = slashClassName; *cp != '\0'; cp++)  
        if (*cp == '.')  
            *cp = '/';  
  
    startClass = env->FindClass(slashClassName);  
    if (startClass == NULL) {  
        ......  
    } else {  
        startMeth = env->GetStaticMethodID(startClass, "main",  
            "([Ljava/lang/String;)V");  
        if (startMeth == NULL) {  
            ......  
        } else {  
            env->CallStaticVoidMethod(startClass, startMeth, strArray);  
            ......  
        }  
    }  
  
    ......  
}  
 //\frameworks\base\core\jni\androidRuntime.cpp startVm() 
 int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    /*
     * Initialize the VM.
     *
     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
     * If this call succeeds, the VM is ready, and we can start issuing
     * JNI calls.
     */
     //startVM的前半部分是在处理虚拟机的启动参数,处理完配置参数后, 会调用libart.so提供的一个接口: JNI_CreateJavaVM函数
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }
    return 0;
}
 
// /art/runtime/java_vm_ext.cc JNI_CreateJavaVM()
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void *vm_args) {
 ScopedTrace trace( FUNCTION );
 
 const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
 
 if (JavaVMExt::IsBadJniVersion(args->version)) {
   LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
 return JNI_EVERSION; 8
}
 RuntimeOptions options;
 for (int i = 0; i < args->nOptions; ++i) {
     JavaVMOption* option = &args->options[i];
     options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
 }
 bool ignore_unrecognized = args->ignoreUnrecognized;
 //通过Runtime的create方法创建单例的Runtime对象
 if (!Runtime::Create(options, ignore_unrecognized)) {
 return JNI_ERR; 
}

 // Initialize native loader. This step makes sure we have
 // everything set up before we start using JNI.
 android::InitializeNativeLoader(); 
 Runtime* runtime = Runtime::Current();
 bool started = runtime->Start();
 if (!started) {
   delete Thread::Current()->GetJniEnv();
   delete runtime->GetJavaVM();
   LOG(WARNING) << "CreateJavaVM failed";
 return JNI_ERR; 31
}

 *p_env = Thread::Current()->GetJniEnv();
 *p_vm = runtime->GetJavaVM();
 return JNI_OK; 36
}

Runtime的create方法创建单例的Runtime对象, runtime负责提供art虚拟机的运行时环境, 然后调用其init方法来初始化虚拟机。

  1. new gc::heap(), 创建Heap对象, 这是虚拟机管理对内存的起点。
  2. new JavaVmExt(),创建Java虚拟机实例。
  3. Thread::attach(), attach主线程
  4. 创建ClassLinker
  5. 初始化ClassLinker,成功attach到runtime环境后, 创建ClassLinker实例负责管理java class

除了系统的JNI接口(” javacore” , “nativehelper” ), android framework 还有大量的Native实现,Android将所有这些接口一次性的通过start_reg()来完成。

// \frameworks\base\core\jni\androidRuntime.cpp startReg()
/*
 * Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ATRACE_NAME("RegisterAndroidNatives");
    /*
     * This hook causes all future threads created in this process to be
     * attached to the JavaVM.  (This needs to go away in favor of JNI
     * Attach calls.)
     */
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    ALOGV("--- registering native functions ---\n");

    /*
     * Every "register" function calls one or more things that return
     * a local reference (e.g. FindClass).  Because we haven't really
     * started the VM yet, they're all getting stored in the base frame
     * and never released.  Use Push/Pop to manage the storage.
     */
    env->PushLocalFrame(200);

    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    //createJavaThread("fubar", quickTest, (void*) "hello");

    return 0;
}
Step 3. ZygoteInit.main
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {  
    ......  
  
   public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();//新建Zygote服务器端
        
        ...
        
        final Runnable caller;
        try {
            ...
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
            //app_main.cpp中传的start-system-server参数, 在这里有用 
                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.");
            }

            zygoteServer.registerServerSocketFromEnv(socketName);//注册Socket
            // 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());
                preload(bootTimingsTraceLog);// 在有些情况下我们需要在第一个fork之前进行预加载资源
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();//主动进行一次资源GC
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false, 0);

            Zygote.nativeSecurityInit();

            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();

            ZygoteHooks.stopZygoteNoThreadCreation();

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }
  
    ......  
}  
// \frameworks\base\core\java\com\android\internal\os\ZygotInit.java preload()
static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");
        bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
        beginIcuCachePinning();
        bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
        bootTimingsTraceLog.traceBegin("PreloadClasses");
        //加载指定的类到内存并且初始化, 使用的Class.forName(class, true, null);方式
        preloadClasses();
        bootTimingsTraceLog.traceEnd(); // PreloadClasses
        bootTimingsTraceLog.traceBegin("PreloadResources");
        //加载Android通用的资源(不是apk资源), 比如drawable、 color
        preloadResources();
        bootTimingsTraceLog.traceEnd(); // PreloadResources
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
        nativePreloadAppProcessHALs();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
        //加载OpenGL
        preloadOpenGL();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        //加载共用的Library
        preloadSharedLibraries();
        //加载文字资源
        preloadTextResources();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        // 为了内存共享, WebViewFactory进行任何初始化都要在Zygote进程中
        WebViewFactory.prepareWebViewInZygote();
        endIcuCachePinning();
        warmUpJcaProviders();
        Log.d(TAG, "end preload");

        sPreloadComplete = true;
    }
// \frameworks\base\core\java\com\android\internal\os\ZygotInit.java forkSystemServer()
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_PTRACE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG,
            OsConstants.CAP_WAKE_ALARM,
            OsConstants.CAP_BLOCK_SUSPEND
        );
        /* Containers run without some capabilities, so drop any caps that are not available. */
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data;
        try {
            data = Os.capget(header);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to capget()", ex);
        }
        capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);

        /* Hardcoded command line to start the system server */
        //启动SystemServer的命令行, 部分参数写死
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);//会设 置InvokeWith参数, 这个参数在接下来的初始化逻辑中会有调用

            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer) {
                parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process */
            /* 创建 system server 进程 */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid,
                    parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {//如果是第一次创建的话pid==0
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

ZygoteInit.forkSystemServer() 方法fork 出一个新的进程, 这个进程就是SystemServer进程。 fork出来的子进程在handleSystemServerProcess 里开始初始化工作, 主要工作分为:

  • prepareSystemServerProfile( ) 方法中将SYSTEMSERVERCLASSPATH中的AppInfo加载到VM中。
  • 判断fork args中是否有invokWith参数, 如果有则进行WrapperInit.execApplication 。 如果没有则调用
 private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
            // Capturing profiles is only supported for debug or eng builds since selinux normally
            // prevents it.
            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                try {
                    //将SYSTEMSERVERCLASSPATH中的AppInfo加载到VM中
                    prepareSystemServerProfile(systemServerClasspath);
                } catch (Exception e) {
                    Log.wtf(TAG, "Failed to set up system server profile", e);
                }
            }
        }

        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }
            //判断fork args中是否有invokWith参数, 如果有则进行WrapperInit.execApplication
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);

            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
             //调用zygoteInit
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

3.SystemServer启动过程

System Server 是Zygote fork 的第一个Java 进程, 这个进程非常重要, 因为他们有很多的系统线程, 提供所有核心的系统服务,WindowManager、ActivityManager 它们都是运行在system_server的进程里。 还有很多“ Binder-x” 的线程, 它们是各个Service为了响应应用程序远程调用请求而创建的。 除此之外, 还有很多内部的线程, 比如 ” UI thread” , “ InputReader” , “ InputDispatch” 等, 现在我们只关心System Server是如何创建起来的。

// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
        new SystemServer().run();
}
/**
* 初始化必要的SystemServer环境参数, 比如系统时间、 默认时区、 语言、 load一些Library等等,
* 初始化Looper, 我们在主线程中使用到的looper就是在SystemServer中进行初始化的
* 初始化Context, 只有初始化一个Context才能进行启动Service等操作, 这里看一下源码:
*/
    private void run() {

        try {
            traceBeginAndSlog("InitBeforeStartServices");
            // If a device's clock is before 1970 (before 0), a lot of
            // APIs crash dealing with negative numbers, notably
            // java.io.File#setLastModified, so instead we fake it and
            // hope that time from cell towers or NTP fixes it shortly.
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                Slog.w(TAG, "System clock is before 1970; setting to 1970.");
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }

            //
            // Default the timezone property to GMT if not set.
            //
            String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
            if (timezoneProperty == null || timezoneProperty.isEmpty()) {
                Slog.w(TAG, "Timezone not set; setting to GMT.");
                SystemProperties.set("persist.sys.timezone", "GMT");
            }

            // If the system has "persist.sys.language" and friends set, replace them with
            // "persist.sys.locale". Note that the default locale at this point is calculated
            // using the "-Duser.locale" command line flag. That flag is usually populated by
            // AndroidRuntime using the same set of system properties, but only the system_server
            // and system apps are allowed to set them.
            //
            // NOTE: Most changes made here will need an equivalent change to
            // core/jni/AndroidRuntime.cpp
            if (!SystemProperties.get("persist.sys.language").isEmpty()) {
                final String languageTag = Locale.getDefault().toLanguageTag();

                SystemProperties.set("persist.sys.locale", languageTag);
                SystemProperties.set("persist.sys.language", "");
                SystemProperties.set("persist.sys.country", "");
                SystemProperties.set("persist.sys.localevar", "");
            }

            // The system server should never make non-oneway calls
            Binder.setWarnOnBlocking(true);
            // The system server should always load safe labels
            PackageItemInfo.setForceSafeLabels(true);
            // Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
            SQLiteCompatibilityWalFlags.init(null);

            // Here we go!
            Slog.i(TAG, "Entered the Android system server!");
            int uptimeMillis = (int) SystemClock.elapsedRealtime();
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
            if (!mRuntimeRestart) {
                MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
            }

            // In case the runtime switched since last boot (such as when
            // the old runtime was removed in an OTA), set the system
            // property so that it is in sync. We can | xq oqi't do this in
            // libnativehelper's JniInvocation::Init code where we already
            // had to fallback to a different runtime because it is
            // running as root and we need to be the system user to set
            // the property. http://b/11463182
            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

            // Mmmmmm... more memory!
            VMRuntime.getRuntime().clearGrowthLimit();

            // The system server has to run all of the time, so it needs to be
            // as efficient as possible with its memory usage.
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

            // Some devices rely on runtime fingerprint generation, so make sure
            // we've defined it before booting further.
            Build.ensureFingerprintProperty();

            // Within the system server, it is an error to access Environment paths without
            // explicitly specifying a user.
            Environment.setUserRequired(true);

            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);

            // Within the system server, when parceling exceptions, include the stack trace
            Parcel.setStackTraceParceling(true);

            // Ensure binder calls into the system always run at foreground priority.
            BinderInternal.disableBackgroundScheduling(true);

            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            // Prepare the main looper thread (this thread).
            android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper();
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

            // Initialize native services.
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // Initialize the system context.
            createSystemContext();

            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        //初始化SystemServiceManager,用来管理启动service, SystemServiceManager中封装了启动Service的startService方法启动系统必要的Service, 启动service的流程又分成三步走:
        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();
        }
        StrictMode.initVmDefaults(null);

        if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
            int uptimeMillis = (int) SystemClock.elapsedRealtime();
            MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);
            final int MAX_UPTIME_MILLIS = 60 * 1000;
            if (uptimeMillis > MAX_UPTIME_MILLIS) {
                Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
                        "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
            }
        }

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

启动BootstrapServices,就是系统必须需要的服务, 这些服务直接耦合性很高, 所以干脆就放在一个方
法里面一起启动, 比如PowerManagerService、 RecoverySystemService、 DisplayManagerService、
ActivityManagerService等等启动以基本的核心Service, 很简单, 只有三个BatteryService、
UsageStatsService、 WebViewUpdateService启动其它需要用到的Service, 比如NetworkScoreService、 AlarmManagerService

// frameworks/base/services/java/com/android/server/SystemServer.java
//ActivityThread就是这个时候生成的,以下是Context创建流程。
private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}


// frameworks/base/core/java/android/app/ActivityThread.java
    public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                mSystemContext = ContextImpl.createSystemContext(this);
            }
            return mSystemContext;
        }
    }

// frameworks/base/core/java/android/app/ContextImpl.java
//ContextImpl是Context类的具体实现, 里面封装完成了生成几种常用的createContext的方法:
 static ContextImpl createSystemContext(ActivityThread mainThread) {
        ...
        return context;
    }

    /**
     * System Context to be used for UI. This Context has resources that can be themed.
     * Make sure that the created system UI context shares the same LoadedApk as the system context.
     */
    static ContextImpl createSystemUiContext(ContextImpl systemContext) {
       ...
        return context;
    }

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        ...
        return context;
    }

    static ContextImpl createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
            Configuration overrideConfiguration) {
       ...
        return context;
    }

总结

以上就是今天学习的笔记内容,本文仅仅简单介绍了Android系统启动流程,而Android启动流程还有许多地方是值得深入学习的。总结以上内容:

  • init 根据init.rc 运行 app_process, 并携带‘– zygote’ 和 ’ – startSystemServer’ 参
    数。
  • AndroidRuntime.cpp::start() 里将启动JavaVM, 并且注册所有framework相关的系统JNI接口。
  • 第一次进入Java世界, 运行ZygoteInit.java::main() 函数初始化Zygote. Zygote 并创建Socket
    的 se
    rver 端。
  • 然后fork一个新的进程并在新进程里初始化SystemServer. Fork之前, Zygote是preload常用的
    Java类库, 以及系统的resources, 同时GC() 清理内存空间, 为子进程省去重复的工作。
  • SystemServer 里将所有的系统Service初始化, 包括ActivityManager 和 WindowManager, 他们
    是应用程序运行起来的前提。
  • 依次同时, Zygote监听服务端Socket, 等待新的应用启动请求。
  • ActivityManager ready 之后寻找系统的“Startup” Application, 将请求发给Zygote。
  • Zygote收到请求后, fork出一个新的进程。
  • Zygote监听并处理SystemServer 的 SIGCHID 信号, 一旦System Server崩溃, 立即将自己杀死。
    init会重启Zygote.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值