​#Android#​

init进程启动流程

来自Android系统初探

image

源码路径: system/core/init (由多个源文件共同组成)

查看该路径下的文件

image

Android系统中, init进程用户空间中的第一个进程, 进程号为1.

功能:

  • 创建Zygote(孵化器)
  • 初始化和启动属性服务

引入init进程(前提)

在init进程之前, 需要Android系统启动流程的前几步, 来引入init进程.

概述

根据前面的进程图

  • Loader层加载BootLoader

  • 通过BootLoader进入到Kernal层启动swapper进程

    • 一方面运行kthreadd进程, 加载内核层的功能进程
    • 一方面加载驱动, 并通过将这些硬件驱动通过系统调用的接口提供给HAL层
  • 通过系统调用的形式进入到了Native层, 主要还是启动了init进程

启动电源 -> 系统启动

  • 按下电源键
  • 引导芯片代码从预定义的地方(固化在ROM(硬盘)中)开始执行
  • 加载引导程序BootLoader到RAM(内存)中
  • 执行BootLoader

引导程序BootLoader

BootLoader在Android系统开始前的小程序, 主要功能: 把操作系统拉起来并运行, 检查RAM, 初始化硬件参数(这个在深入理解Android内核思想中有提到过)

初始化硬件后, BootLoader根据不同的按键组合切换模式:

  • 电源键: 启动Android系统
  • 电源键 + 音量加: 进入Recovery模式
  • 电源键 + 音量减: 进入FastBoot模式

Linux内核启动

具体过程

  • 启动Kernel层的swapper进程(pid = 0): 又称为idle进程, 系统初始化过程Kernel开启的第一个进程, 用于初始化进程管理, 内存管理, 加载Display, Camera Driver, Binder Driver(驱动)等工作大致分为以下: (注意: 前面说的init进程用户空间中的第一个进程, 而swapper内核空间中的第一个进程)

    • 设置缓存
    • 设置被保护存储器
    • 设置计划列表
    • 加载驱动
  • 启动kthreadd进程(pid = 2): 也是一个内核进程, 是下面创建的进程的鼻祖

    • 创建内核工作线程kworkder,
    • 软中断线程ksoftirqd,
    • 内核守护进程thermal
  • 启动完成后:

    • 在系统文件中寻找init.rc文件
    • 启动init进程

init进程启动

  • 创建Zygote(孵化器)
  • 初始化和启动属性服务

init进程入口函数

源码路径: system/core/init/init.cpp

// ############################################################################################################################################################################################################################
int main(int argc, char** argv) {
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    if (!strcmp(basename(argv[0]), "watchdogd")) {
        return watchdogd_main(argc, argv);
    }

    if (REBOOT_BOOTLOADER_ON_PANIC) {
        install_reboot_signal_handlers();
    }

    add_environment("PATH", _PATH_DEFPATH);

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

    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();

        // Clear the umask.
        umask(0);

        // 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("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);
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));

        // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
        // talk to the outside world...
	// 初始化Kernel的Log, 这样可以从外界获取Kernel的日志
        InitKernelLogging(argv);

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

        if (!DoFirstStageMount()) {
            LOG(ERROR) << "Failed to mount required partitions early ...";
            panic();
        }

        SetInitAvbVersionInRecovery();

        // Set up SELinux, loading the SELinux policy.
        selinux_initialize(true);

        // We're in the kernel domain, so re-exec init to transition to the init domain now
        // that the SELinux policy has been loaded.
        if (restorecon("/init") == -1) {
            PLOG(ERROR) << "restorecon failed";
            security_failure();
        }

        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", StringPrintf("%" PRIu64, start_ms).c_str(), 1);

        char* path = argv[0];
        char* args[] = { path, nullptr };
        execv(path, args);

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

    // 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(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();

    // 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.
    selinux_initialize(false);
    selinux_restore_context();

    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(ERROR) << "epoll_create1 failed";
        exit(1);
    }

    // 设置子进程的信号处理函数##################################################################################################################################################################################
    signal_handler_init();
    // 导入默认的环境变量
    property_load_boot_defaults();
    export_oem_lock_status();
    // 启动属性服务##################################################################################################################################################################################
    start_property_service();
    set_usb_controller();

    const BuiltinFunctionMap function_map;
    Action::set_function_map(&function_map);

    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service",std::make_unique<ServiceParser>());
    parser.AddSectionParser("on", std::make_unique<ActionParser>());
    parser.AddSectionParser("import", std::make_unique<ImportParser>());
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
	// 配置init.rc配置文件##################################################################################################################################################################################
        parser.ParseConfig("/init.rc");
        parser.set_is_system_etc_init_loaded(
                parser.ParseConfig("/system/etc/init"));
        parser.set_is_vendor_etc_init_loaded(
                parser.ParseConfig("/vendor/etc/init"));
        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
    } else {
        parser.ParseConfig(bootscript);
        parser.set_is_system_etc_init_loaded(true);
        parser.set_is_vendor_etc_init_loaded(true);
        parser.set_is_odm_etc_init_loaded(true);
    }

    // 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) parser.DumpState();

    ActionManager& am = ActionManager::GetInstance();

    am.QueueEventTrigger("early-init");

    // 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");
    // ... so that we can start queuing up actions that require stuff from /dev.
    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
    am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
    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(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    // 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;

        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
	    // 内部遍历执行每个action中携带的command对应的执行函数
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
	    // 重启死去的进程##################################################################################################################################################################################
            restart_processes();

            // If there's a process that needs restarting, wake up in time for that.
            if (process_needs_restart_at != 0) {
                epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
                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_event 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)();
        }
    }

    return 0;
}

init的功能

  • 创建和挂载系统运行时目录(即系统运行才存在的目录)

    • tmpfs
    • devpts
    • proc
    • sysfs
    • selinuxfs
  • 属性服务的初始化和启动

    • property_init();
    • start_property_service();
  • 设置子进程信号处理函数signal_handler_init();

    • 其源代码位于system/core/init/signal_handler.cpp中, 用于防止init进程的子进程变成僵尸进程, 子进程暂停或终止时发出SIGCHLD信号, 而该函数接收SIGCHLD信号并作出处理.(其内部其实只处理终止进程的SIGCHLD信号)
    • 假设Zygote进程终止, signal_handler_init​函数内部调用handle_signal()​, 经过层层函数调用, 最终找到Zygote进程并移除, 最后重启Zygote服务的启动脚本中带有onrestart选项的服务(如init.zygote64.rc), Zygote会在上面代码中的restart_processes();​处重启
  • 解析init.rc文件, 位于上面代码中parser.ParseConfig("/init.rc");​处

    • 解析函数位于system/core/init/init_parse.cpp文件

解析init.rc

简介

路径: system/core/rootdir/init.rc

init.rc是一个非常重要的配置文件, 由Android Init Language(Android初始化语言)编写的脚本

主要包含5种类型的语句:

  • Action
  • Command
  • Service
  • Option
  • Import

各个类型都有相应的类进行解析

  • Action类型语句采用ActionParser进行解析
  • Service类型语句采用ServiceParser(路径: system/core/init/service.cpp)进行解析

解析类源码

我们主要学习ServiceParser的源码, 两个主要函数:

  • ParseSection: 解析Service的rc文件, 搭建Service的主要框架
  • ParseLineSection: 解析子项
bool ServiceParser::ParseSection(const std::vector<std::string>& args,
                                 std::string* err) {
    if (args.size() < 3) { // 判断Service是否有name与可执行程序路径 (比如: service zygote /system/xxx)
        *err = "services must have a name and a program";
        return false;
    }

    const std::string& name = args[1];
    if (!IsValidName(name)) { // 检查service名称是否合法
        *err = StringPrintf("invalid service name '%s'", name.c_str());
        return false;
    }

    std::vector<std::string> str_args(args.begin() + 2, args.end()); // Service链表中添加Service对象
    service_ = std::make_unique<Service>(name, str_args);
    return true;
}


bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
                                     const std::string& filename, int line,
                                     std::string* err) const {
    return service_ ? service_->ParseLine(args, err) : false;
}

init.rc源码

on init
    sysclktz 0
    copy /proc/cmdline /dev/urandom
    copy /default.prop /dev/urandom
...
on boot
    ifup lo
    hostname localhost
    domainname localdomain
    setrlimit 13 40 40
...

on init​和on boot​是Action类型语句, 其格式如下

on <trigger> [&& <trigger>]*   // 设置触发器
    <command>
    <command>  // 动作触发之后执行的命令

Service类型语句是Zygote的主要语句, 其格式如下

service <name> <pathname> [ <argument> ]* //<service名称><执行程序路径><参数>
    <option>   // option是service的修饰词, 影响什么时候, 如何启动service
    <option>
    ....

Zygote初始化init脚本

Android8.0对init.rc拆分, 每个服务对应一个rc文件, Zygote启动脚本在init.zygoteXX.rc中定义 (比如: init.zygote64.rc是64位处理器的zygote启动脚本)

路径: system/core/rootdir/init.zygote64.rc

HomeHistoryAnnotateLine#NavigateDownload
  only in init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

分析:

  • service头

    • 服务名称: zygote

    • 可执行程序路径: /system/bin/app_process64

    • 参数:

      • -Xzygote
      • /system/bin
      • --zygote
      • --start-system-server
  • option (class main): 指Zygote的classname为main

  • ....

init启动Zygote

前面给出了启动Zygote的三个前提:

  • Zygote的初始化脚本
  • 初始化脚本使用了Service语句, 所以有了ServiceParser
  • 在init进程中解析Zygote初始化脚本

有了这些前提, 我们再来解析init.rc配置代码 (注意不是init.zygote64.rc)

...
on nonencrypted
    exec - root -- /system/bin/update_verifier nonencrypted
    class_start main
    class_start late_start
...
  • class_start是一个COMMAND(命令), 对应函数为do_class_start()​. 后面跟着main, 表示: 启动classname为main的class. 而前面init.zygote64.rc中注明了zygote的classname为mian, 所以启动了Zygote.

    • do_class_start()​中调用了ForEachServiceInClass()​(该函数遍历Service链表, 找到classname为main的Zygote, 并执行StartIfNotDisabled()​)代码如下:

      static int do_class_start(const std::vector<std::string>& args) {
          ServiceManager::GetInstance().
              ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
          return 0;
      }
      
    • 继续跟进StartIfNotDisabled()​, 其代码如下:

      bool Service::StartIfNotDisabled() {
          if (!(flags_ & SVC_DISABLED)) { // 如果Service在其rc文件中未设置disabled选项, 则调用Start()启动Service
              return Start();
          } else {
              flags_ |= SVC_DISABLED_START;
          }
          return true;
      }
      
    • 跟进Start()​, 其代码太长, 只描述其大致的作用

      • 判断Service是否已经运行, 若已运行则不重复启动
      • 判断启动Service的可执行程序是否存在, 不存在则不启动Service
      • fork创建子进程, 调用execve()启动相应的Service
    • 通过execve()启动了Service后, 则进入相应程序的main函数中, 以Zygote为例, 可执行程序/system/bin/cmds/app_process/app_main.cpp其代码为:

      int main(int argc, char* const argv[]) {
          if (zygote) {
      	runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
          } else if {
      	fprintf(stderr, "Error: no class name or --zygote supplied.\n");
      	...
      	return 10;
          }
      }
      
    • 上面的main函数使用了runtime来启动Zygote

属性服务

init进程的另一个作用就是: 启动Android的属性服务, 该功能提供下面的服务:

  • 采用键值对形式记录用户, 软件的一些使用信息, 即使系统重启, 还是能根据注册表的记录进行初始化工作

init中启动属性服务

在前面init进程入口函数中, 有两行:

  • property_init(): 属性服务初始化
  • start_property_service(): 启动属性服务

属性服务初始化与启动

property_init

路径: /system/core/init/property_service.cpp

作用: 调用__system_property_area_init()​ (初始化属性的内存区域), 根据其返回值判断初始化是否成功.

void property_init() {
    if (__system_property_area_init()) {
        LOG(ERROR) << "Failed to initialize property area";
        exit(1);
    }
}

start_property_service

路径: /system/core/init/property_service.cpp

作用:

void start_property_service() {
    property_set("ro.property_service.version", "2");

    property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                                    0666, 0, 0, NULL);
    if (property_set_fd == -1) {
        PLOG(ERROR) << "start_property_service socket creation failed";
        exit(1);
    }

    listen(property_set_fd, 8);

    register_epoll_handler(property_set_fd, handle_property_set_fd);
}
  • create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0666, 0, 0, NULL);​: 创建了非阻塞的Socket
  • listen(property_set_fd, 8);​: 表示属性服务最多可以为8个视图设置服务的用户提供服务
  • register_epoll_handler(property_set_fd, handle_property_set_fd);​: 表示当property_set_fd中有数据到来时, init将调用handle_property_set_fd函数进行处理

服务处理客户端请求

handle_property_set_fd()

属性服务接收到请求时, 调用handle_property_set_fd函数, 核心是27行的switch​语句

  • handle_property_set(socket, prop_value, prop_value, true);
static void handle_property_set_fd() {
    static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */

    int s = accept4(property_set_fd, nullptr, nullptr, SOCK_CLOEXEC);
    if (s == -1) {
        return;
    }

    struct ucred cr;
    socklen_t cr_size = sizeof(cr);
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
        close(s);
        PLOG(ERROR) << "sys_prop: unable to get SO_PEERCRED";
        return;
    }

    SocketConnection socket(s, cr);
    uint32_t timeout_ms = kDefaultSocketTimeout;

    uint32_t cmd = 0;
    if (!socket.RecvUint32(&cmd, &timeout_ms)) {
        PLOG(ERROR) << "sys_prop: error while reading command from the socket";
        socket.SendUint32(PROP_ERROR_READ_CMD);
        return;
    }

    switch (cmd) {
    case PROP_MSG_SETPROP: {
        char prop_name[PROP_NAME_MAX];
        char prop_value[PROP_VALUE_MAX];

	// 如果Socket读取不到属性数据则返回###################################################################################################################################################################################################
        if (!socket.RecvChars(prop_name, PROP_NAME_MAX, &timeout_ms) ||
            !socket.RecvChars(prop_value, PROP_VALUE_MAX, &timeout_ms)) {
          PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP): error while reading name/value from the socket";
          return;
        }

        prop_name[PROP_NAME_MAX-1] = 0;
        prop_value[PROP_VALUE_MAX-1] = 0;

        handle_property_set(socket, prop_value, prop_value, true);##############################################################################################################################################################################
        break;
      }

    case PROP_MSG_SETPROP2: {
        std::string name;
        std::string value;
        if (!socket.RecvString(&name, &timeout_ms) ||
            !socket.RecvString(&value, &timeout_ms)) {
          PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP2): error while reading name/value from the socket";
          socket.SendUint32(PROP_ERROR_READ_DATA);
          return;
        }

        handle_property_set(socket, name, value, false);
        break;
      }

    default:
        LOG(ERROR) << "sys_prop: invalid command " << cmd;
        socket.SendUint32(PROP_ERROR_INVALID_CMD);
        break;
    }
}

handle_property_set()

handle_property_set_fd()​中被调用, 在Android7.0中属于handle_property_set_fd()​, 但是8.0被做了进一步的封装

系统属性分为两类:

  • 普通属性:
  • 控制属性: 用于执行一些命令 (比如开机动画使用了该类属性)
static void handle_property_set(SocketConnection& socket,
                                const std::string& name,
                                const std::string& value,
                                bool legacy_protocol) {
  const char* cmd_name = legacy_protocol ? "PROP_MSG_SETPROP" : "PROP_MSG_SETPROP2";
  if (!is_legal_property_name(name)) {
    LOG(ERROR) << "sys_prop(" << cmd_name << "): illegal property name \"" << name << "\"";
    socket.SendUint32(PROP_ERROR_INVALID_NAME);
    return;
  }

  struct ucred cr = socket.cred();
  char* source_ctx = nullptr;
  getpeercon(socket.socket(), &source_ctx);

  // 如果属性名称以"ctl."开头, 说明是控制属性
  if (android::base::StartsWith(name, "ctl.")) {
    // 检查客户端权限
    if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) {
      // 设置控制属性
      handle_control_message(name.c_str() + 4, value.c_str());
      if (!legacy_protocol) {
        socket.SendUint32(PROP_SUCCESS);
      }
    } else {
      LOG(ERROR) << "sys_prop(" << cmd_name << "): Unable to " << (name.c_str() + 4)
                 << " service ctl [" << value << "]"
                 << " uid:" << cr.uid
                 << " gid:" << cr.gid
                 << " pid:" << cr.pid;
      if (!legacy_protocol) {
        socket.SendUint32(PROP_ERROR_HANDLE_CONTROL_MESSAGE);
      }
    }
  } else { // 该分支是普通属性, 检查客户端权限
    if (check_mac_perms(name, source_ctx, &cr)) {
      uint32_t result = property_set(name, value); // 对普通属性进行修改, 就是修改键值对
      if (!legacy_protocol) {
        socket.SendUint32(result);
      }
    } else {
      LOG(ERROR) << "sys_prop(" << cmd_name << "): permission denied uid:" << cr.uid << " name:" << name;
      if (!legacy_protocol) {
        socket.SendUint32(PROP_ERROR_PERMISSION_DENIED);
      }
    }
  }

  freecon(source_ctx);
}

init进程启动总结

init进程的主要工作:

  • 创建和挂载启动所需文件目录
  • 初始化和启动属性服务
  • 解析init.rc配置文件并启动Zygote进程

Zygote进程启动过程

Zygote概述

也称为孵化器, 使用fork()的形式创建Zygote子进程, 其子进程有:

  • DVM(Dalvik虚拟机)
  • ART
  • 应用程序进程
  • 系统关键服务的SystemServer进程 (别跟前面属性服务搞混了, 不清楚就看开头的层次图)

注意: Zygote进程启动时自动创建DVM或ART, 所以后面fork的时候所有的子进程都自带一个虚拟机副本.

Zygote启动脚本

路径: system/core/rootdir

在init.rc文件中采用了Import类型语句来引入Zygote启动脚本, 所以启动脚本都是由Android Init Language编写的.

import /init.$(ro.zygote).rc // $()表示变量的意思

可以看到最终引入的文件名是一个变量, 也就是说不是固定的, 下面是可能的Zygote启动脚本文件:

  • init.zygote32.rc
  • init.zygote32_64.rc
  • init.zygote64.rc
  • init.zygote64_32.rc

下面分别分析这些脚本文件

init.zygote32.rc

表示支持纯32位程序

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

组成:

  • service头

    • 进程名: zygote
    • 可执行文件路径: /system/bin/app_process
    • 各个参数: -Xzygote /system/bin --zygote --start-system-server
  • 修饰词

    • (class main) 类名: main
    • (onrestart restart audioserver): 如果audioserver终止, 则重启
    • (onrestart restart cameraserver): 如果cameraserver终止, 则重启
    • (onrestart restart media): 如果media终止, 则重启
    • (onrestart restart netd): 如果netd终止, 则重启
    • (onrestart restart wificond): 如果wificond终止, 则重启

init.zygote32_64.rc

表示既支持32位程序也支持64位程序

service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    priority -20
    user root
    group root readproc
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

有两个Service类型语句, 说明会启动两个Zygote进程

  • 第一个Zygote进程

    • 名称: zygote
    • 功能: 执行32位程序
    • 主次: 作为主模式
  • 第二个Zygote进程

    • 名称: app_process32
    • 功能: 执行64位程序
    • 主次: 作为辅模式

Zygote进程启动过程

Zygote是在init进程中解析init.rc(import了相应的zygote.rc)并将Zygote的Server对象添加到链表中, 然后通过fork加上execve启动了app_process64可执行程序.

根据Server结构体, 启动了app_process64后根据Service语句修改进程名, 所以进程名为Zygote, 执行app_main.cpp中的AppRuntime的start方法来启动Zygote进程.

启动过程的时序图如下所示

5FAB37EFFF783B51BB58D3CC968AD639

app_main (Native)

路径: frameworks/base/cmds/app_process/app_main.cpp

大致逻辑:

  • Zygote通过fork创建子进程, 所以子进程逻辑也会进入到app_main中, 为了区分不同类型的子进程

    • 判断arg参数中是否包含了"--zygote", 如包含则说明运行在Zygote进程中, 并将bool变量zygote设置为true

      • 如果是zygote会在下方注释6处调用AppRuntime的start函数
    • 判断arg是否包含"--start-system-server", 如包含则说明运行在SystemServer进程中, 并将bool变量startSystemServer设置为true

int main(int argc, char* const argv[])
{
    if (!LOG_NDEBUG) {
      String8 argv_String;
      for (int i = 0; i < argc; ++i) {
        argv_String.append("\"");
        argv_String.append(argv[i]);
        argv_String.append("\" ");
      }
      ALOGV("app_process main with argv: %s", argv_String.string());
    }

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    const char* spaced_commands[] = { "-cp", "-classpath" };
    // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
    bool known_command = false;

    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {
          runtime.addOption(strdup(argv[i]));
          ALOGV("app_process main add known option '%s'", argv[i]);
          known_command = false;
          continue;
        }

        for (int j = 0;
             j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
             ++j) {
          if (strcmp(argv[i], spaced_commands[j]) == 0) {
            known_command = true;
            ALOGV("app_process main found known command '%s'", argv[i]);
          }
        }

        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }

        runtime.addOption(strdup(argv[i]));
        ALOGV("app_process main add option '%s'", argv[i]);
    }

    // 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进程中, 则将zygote变量设为true
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
	    // 如果当前运行在SystemServer进程中, 则将startSystemServer设置为true
            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;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);

        if (!LOG_NDEBUG) {
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) {
            restOfArgs.append("\"");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("\" ");
          }
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        }
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    // 如果运行在Zygote进程中
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote); // 6  ########################################################################################################################
    } 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.");
    }
}

AndroidRuntime (Native)

路径: frameworks/base/core/jni/AndroidRuntime.cpp

上面Zygote子进程调用的AppRuntime的start函数

AndroidRuntime通过JNI接口实现了逻辑Native层进入Java框架层, 大致逻辑如下

  • 31行: 调用startVm()​函数启动Java虚拟机

  • 37行: 调用startReg(env)​为Java虚拟机注册JNI方法

  • 51行: 调用env->NewStringUTF(className)

    • className见前面的app_main中调用的start参数runtime.start("com.android.internal.os.ZygoteInit", args, zygote);​: 是"com.android.internal.os.ZygoteInit"
  • 62行: 调用toSlashClassName(className)​将"."换成"/"

  • 64行: 调用env->FindClass(slashClassName);​找到该类

  • 70行: 调用jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");​找到该类的main方法

  • 77行: 调用env->CallStaticVoidMethod(startClass, startMeth, strArray);​调用了Java层的main方法, 至此逻辑从Native层转换至Java框架层

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");

    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    // 启动Java虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 为Java虚拟机注册JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    // 从app_main的main函数的值className为com.android.internal.os.ZygoteInit
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    // 将className的"."换成"/"
    char* slashClassName = toSlashClassName(className);
    // 找到ZygoteInit
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
	// 找到Zygote的main方法
        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 {
	    // 通过JNI调用ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

ZygoteInit (Java)

路径:

app_main (Native)​的逻辑中使用了AndroidRuntime (Native)​的start()方法, 成功找到了ZygoteInit类, 并运行其main()静态方法

大致逻辑:

  • 注释一: 通过registerServerSocket()​创建一个Server端的Socket

    • 该Socket用于等待ActivityManagerService请求Zygote来创建新的应用进程
  • 注释二: 预加载类和资源

  • 注释三: 启动SystemServer进程

  • 注释四: 等待AMS请求创建新的应用程序进程

    public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        try {
            // Report Zygote start time to tron unless it is a runtime restart
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            }

            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.enableDdms();
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            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.");
            }

	    // 创建一个Server端的Socket, socketName的值为"zygote"
            zygoteServer.registerServerSocket(socketName); // 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
            // 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); // 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }

            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

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

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

            // Set seccomp policy
            Seccomp.setPolicy();

            ZygoteHooks.stopZygoteNoThreadCreation();

            if (startSystemServer) {
		// 启动SystemServer进程
                startSystemServer(abiList, socketName, zygoteServer); // 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
            }

            Log.i(TAG, "Accepting command socket connections");
	    // 等待AMS请求
            zygoteServer.runSelectLoop(abiList); // 44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444

            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

registerZygoteSocket创建服务端Socket等待AMS (java)

创建一个等待创建新应用进程的Server端Socket.

大致流程:

  • 注释一: 拼接Socket名称, 常量ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_"​, 根据实参拼接起来就是"ANDROID_SOCKET_zygote"

  • 注释二: 将上面的socketname转换成环境变量的值

  • 注释三: 再转换为文件描述符的参数

  • 注释四: 创建文件描述符

  • 注释五: 设置文件描述参数

  • 注释六: 根据文件描述符创建服务端Socket, 注意这里只是创建了Socket, 并没有实现功能, 功能实现需要以下的条件

    • 条件: 在Zygote进程将SystemServer进程启动后
    • 功能: 会在该服务端Socket等待AMS请求Zygote进程来创建新的应用程序进程
    void registerServerSocket(String socketName) {
        if (mServerSocket == null) {
            int fileDesc;
	    // 拼接Socket的名称
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; // 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
            try {
		// 得到Socket的环境变量值
                String env = System.getenv(fullSocketName); // 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
                // 将Socket环境变量的值转换为文件描述符的参数
		fileDesc = Integer.parseInt(env); // 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
		// 创建文件描述符
                FileDescriptor fd = new FileDescriptor(); // 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
                fd.setInt$(fileDesc); // 555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555
		// 创建服务端Socket
                mServerSocket = new LocalServerSocket(fd); // 6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

startSystemServer启动SystemServer进程 (java)

该函数启动了SystemServer, 总体的思路还是fork, 但是有一个Java框架层->Native层的转换:

  • 保存进程启动参数

  • 将字符串数组形式的启动参数转换为Java对象

  • 传入forkSystemServer()

    • 内部调用了nativeForkSystemServer()​是一个Native层方法

      • 最终该Native函数还是使用fork()方法来启动一个新的进程
  • 通过JNI接口返回了不同的PID值

  • 所以在Java框架层也可以控制子进程, 于是在注释四处调用了handleSystemServerProcess()​来处理SystemServer进程

    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
        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
        );
        /* Containers run without this capability, so avoid setting it in that case */
        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
        }
        /* Hardcoded command line to start the system server */
	// 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
	// 创建args数组, 数组用于保存启动SystemServer的启动参数
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args); // 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
	    // 创建一个子进程, 也就是SystemServer进程 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
	// 子进程的逻辑
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
	    // 处理SystemServer进程
            handleSystemServerProcess(parsedArgs); // 44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
        }

        return true;
    }

runSelectLoop

路径: /frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

启动了SystemServer进程后, ZygoteInit的main方法会继续执行其逻辑调用runSelectLoop()

  • 注释一: mServerSocket就是我们在registerZygoteSocket创建服务端Socket等待AMS (java) 中创建的Socket对象

    • 调用getFileDescriptor()​返回Socket的fd字段(文件描述符), 并将其添加到fds列表中
  • 加下来无限等待AMS请求Zygote进程创建新的应用程序进程.

  • 注释二: 遍历将fds中的信息转移到pollFds数组

  • 注释三: 对pollFds进行遍历, 如果i == 0, 说明服务端Socket与客户端连接上了 (这里没搞懂)

    • 也就是说当前Zygote进程与AMS建立了链接
    • 注释四: 通过acceptCommandPeer()得到了ZygoteConnection类, 并其添加到Socket链接列表peers中
    • 然后将ZygoteConnection的fd添加到fds列表中
  • 如果i值不为0

    • 则说明AMS向Zygote进程发送了一个创建应用程序的请求
    • 注释五: 调用ZygoteConnection的runOnce函数创建一个新的应用程序进程
    • 成功创建后将这个连接从Socket连接列表peer和fds中删除
    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(mServerSocket.getFileDescriptor()); // 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
        peers.add(null);

	// 无限循环等待AMS请求
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) { // 22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) { // 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList); // 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce(this); // 5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

Zygote进程启动总结

功能:

  • 创建AppRuntime并调用其start方法, 启动Zygote进程(Native)
  • 创建Java虚拟机并未Java虚拟机注册JNI方法
  • 通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层
  • 通过registerZygoteSocket方法创建服务端Socket, 通过runSelectLoop方法等待AMS请求创建新的应用程序进程
  • 启动SystemServer进程

​#Android#​

SystemServer处理过程

SystemServer进程用于创建系统服务, AMS, WMS, PMS都由它创建

Zygote处理SystemServer进程

Zygote进程启动了SystemServer进程, startSystemServer启动SystemServer进程 (java)

在这里学习Zygote如何处理SystemServer进程

46E1237B075FC81B9CB099B4E47233B3

启动SystemServer (java)

路径: /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

在前面startSystemServer启动SystemServer进程 (java) 中已经解析过了, 这里只把处理的部分贴出来

逻辑:

  • 首先新创建的子进程复制了Zygote进程的地址空间, 也就是说前面的逻辑子进程也执行了, 所以子进程创建了Socket, 但这个Socket没有用处, 所以zygoteServer.closeServerSocket();​关闭了Socket
  • 接着handleSystemServerProcess(parsedArgs);​功能: 启动SystemServer进程
    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
	.....
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
	    // 处理SystemServer进程
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

handleSystemServerProcess() (java)

路径: /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

前面的startSystemServer()​调用了该方法启动SystemServer进程

大致逻辑:

  • 注释一: 创建了PathClassLoader(12章介绍)
  • 注释二: 调用了ZygoteInit的zygoteInit()​方法
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller {
	.......

        if (parsedArgs.invokeWith != null) {
	    ....
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion); // 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

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

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

        /* should never reach here */
    }

zygoteInit() (java)

handleSystemServerProcess() (java)

大致逻辑:

  • 注释一: nativeZygoteInit(), 调用Native层的代码, 来启动Binder线程池, 这样SystemServer进程可使用Binder与其他进程进行通信
  • 注释二: 进入SystemServer的main方法
    public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
	// 启动Binder线程池
        ZygoteInit.nativeZygoteInit(); // 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); // 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
    }

启动Binder线程池

路径: /frameworks/base/core/jni/AndroidRuntime.cpp

由于是一个Native方法, 所以需要到jni目录下去找.

大致逻辑:

int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
            (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
        methods, NELEM(methods));
}

接下来根据包名找到对应的Native方法

逻辑:

  • gCurRuntime是AndroidRuntime类型的指针
  • 调用其onZygoteInit方法
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

接着查看AndroidRuntime的代码, 路径: /frameworks/base/cmds/app_process/app_main.cpp

用于启动一个Binder线程池, 这样SystemServer进程可以通过Binder与其他进程通信

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

进入SystemServer的main方法

路径:

zygoteInit() (java) 中被调用的RuntimeInit.applicationInit()

    protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
	........
	// 调用了invokeStaticMain()方法
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

继续跟进invokeStaticMain()方法

大致逻辑:

  • 注释一: 参数className = "com.android.server.SystemServer"​, forName返回了SystemServer类

  • 注释二: 找到了SystemServer类的main方法

  • 注释三: 将找到的main方法对象传入Zygote.MethodAndArgsCaller()​异常中, 并抛出异常.

    • 为什么不直接调用SystemServer类的main方法呢?
    • 使用抛出异常处理的好处是: 清除所有设置过程所需的堆栈帧, 并让SystemServer的main方法看起来像是SystemServer的入口方法
    • 在main函数之前做了很多的准备工作, 所以需要上面的步骤
    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
        Class<?> cl;

        try {
	    // 通过反射得到SystemServer类
            cl = Class.forName(className, true, classLoader); // 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
	    // 找到SystemServer的main方法
            m = cl.getMethod("main", new Class[] { String[].class }); // 22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
        } 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);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        throw new Zygote.MethodAndArgsCaller(m, argv); // 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
    }
如何处理异常

路径: /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

捕获到抛出的异常后, 调用了该异常对象的run()方法

    public static void main(String argv[]) {

	.......

            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run(); // 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }
跟进异常对象的run()

路径: /frameworks/base/core/java/com/android/internal/os/Zygote.java

该方法时Zygote类中的内部类MethodAndArgsCaller​的静态方法

逻辑:

  • mMethod就是SystemServer的main方法.
  • 调用了mMethod.invoke后, SystemServer的main方法就被动态调用
  • SystemServer进程进入了SystemServer的main方法中
    public static class MethodAndArgsCaller extends Exception
            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 {
                mMethod.invoke(null, new Object[] { mArgs }); // 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
            } 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 new RuntimeException(ex);
            }
        }
    }

解析SystemServer进程

SystemServer的main方法

路径: /frameworks/base/services/java/com/android/server/SystemServer.java

逻辑:

  • 调用了SystemServer()的run()方法
    public static void main(String[] args) {
        new SystemServer().run();
    }

跟进SystemServer的run方法

路径: /frameworks/base/services/java/com/android/server/SystemServer.java

逻辑:

  • 注释一: 加载动态库libandroid_servers.so

  • 注释二: 创建SystemServiceManager, 其功能:

    • 对系统服务进行创建, 启动, 生命周期管理
  • 注释三: startBootstrapServices()​使用了注释二中的SystemServiceManager, 启动了:

    • ActivityManagerService (AMS)
    • PowerManagerService
    • PackageManagerService (PMS)
    • .....
  • 注释四: startCoreService()​方法启动了:

    • DropBoxManagerService
    • BatteryService
    • UsageStatsService
    • WebViewUpdateService
  • 注释五: startOtherServices方法启动了:

    • CameraService
    • AlarmManagerService
    • VrManagerService
    • ......

注意: 上述服务的父类均为SystemService

    private void run() {
        try {
	    // 创建消息Looper
            Looper.prepareMainLooper();

            // 加载动态库libandroid_servers.so
            System.loadLibrary("android_servers"); // 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
            performPendingShutdown();

            // 创建系统的Context
            createSystemContext();

            mSystemServiceManager = new SystemServiceManager(mSystemContext); // 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        try {
            traceBeginAndSlog("StartServices");
	    // 启动引导服务
            startBootstrapServices(); // 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
	    // 启动核心服务
            startCoreServices(); // 4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
	    // 启动其他服务
            startOtherServices(); // 5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
    }

具体服务启动过程

PowerManagerService启动

各个Service启动过程是相似的, 以PowerManagerService为例

startBootstrapServices()​中的启动代码如下:

mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

跟进startService()

路径: /frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

逻辑:

  • 注释一: 将PowerManagerServcie添加到mService中 (mService是用于存储SystemService的ArrayList), 从而完成Service注册工作
  • 注释二: 调用PowerManagerService的onStart函数完成启动Service
    public void startService(@NonNull final SystemService service) {
        // Register it.
	// 注册Service
        mServices.add(service); // 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
        // Start it.
        long time = System.currentTimeMillis();
        try {
	    // 启动service
            service.onStart(); // 22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(System.currentTimeMillis() - time, service, "onStart");
    }

PackageManagerService

除了像PowerManagerService的启动方式之外, 还可以直接调用相应Service对象的main方法

mPackageManagerService = PackageManagerService.main(mSystemContext, installer, nFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

SystemService作用

055C07D50C41D9A346E2F714C04048B8

SystemServer进程总结

功能:

  • 启动Binder线程池, 这样可以与其他进程通信
  • 创建SystemServiceManager, 用于对系统的服务进行创建, 启动, 生命周期管理
  • 启动各种系统服务

Launcher启动过程

Launcher概述

系统启动的最后一步: 启动Launcher应用程序, 其功能是: 用来显示系统中已安装的应用程序.

过程: 启动过程中请求PackageManagerService返回系统中已安装的程序信息, 并将其封装成一个快捷图标显示在系统屏幕上, 用户点击即可启动程序.

功能:

  • 作为Android系统的启动器, 用于启动应用程序
  • 作为Android系统的桌面, 用于显示和管理应用程序的图标或其他桌面组件

Launcher启动过程介绍

SystemServer进程(SystemServer处理过程):

  • 启动AMS(Activity Manager Service)
  • 启动PMS(Package Manager Service)
  • AMS启动Launcher
  • PMS启动后将系统中的应用程序安装完成

时序图如下

D14589A90CFF4D9E69BDC0D0E4F10C64

Launcher启动过程

SystemServer

  • 前面讲到过Zygote进程通过Native启动虚拟机调用了ZygoteInit类, 进入了Java框架层
  • 在ZygoteInit的main方法中调用了startSystemServer()方法
  • 该方法又回到了Native层通过fork()创建了SystemServer进程
  • 通过pid执行子进程的逻辑
  • 以异常抛出的方式进入到了SystemServer的run()方法
  • run()方法调用了startBootstrapServices()​启动了: AMS, PMS
  • run()方法调用了startOtherServices()​: 通过AMS启动了Launcher

startOtherServices()

路径: /frameworks/base/services/java/com/android/server/SystemServer.java

根据前面的流程图, 我们跟进startOtherServices()

逻辑:

  • 调用了ActivityManagerService的systemReady()方法

    • 传入了一个lambda表达式
private void startOtherServices() {
	....
	mActivityManagerService.systemReady(() -> {
		Slog.i(TAG, "Making services ready");
		traceBeginAndSlog("StartActivityManagerReadyPhase");
		mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
		....
	});
	....
}

systemReady()

路径: /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

跟进AMS的systemReady()方法

逻辑:

  • 调用了ActivityStackSupervisor(监管器)的resumeFocusedStackTopActivityLocked()​方法 (resume focused聚焦)

    public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
	.......
        synchronized (this) {
            mStackSupervisor.resumeFocusedStackTopActivityLocked();
            mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
            traceLog.traceEnd(); // ActivityManagerStartApps
            traceLog.traceEnd(); // PhaseActivityManagerReady
        }
    }

resumeFocusedStackTopActivityLocked()

路径: /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

逻辑:

  • return: 调用了AMS的startHomeActivityLocked()
    boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
	......

        // Only resume home activity if isn't finishing.
        if (r != null && !r.finishing) {
            moveFocusableActivityStackToFrontLocked(r, myReason);
            return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
        }
        return mService.startHomeActivityLocked(mCurrentUser, myReason);
    }

startHomeActivityLocked()

路径: /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

逻辑:

  • 注释一: mFactoryTest表示系统的运行模式, 这里是检查系统的运行模式

    • 非工厂模式
    • 低级工厂模式
    • 高级工厂模式
  • 注释二: 创建Launcher所需的Intent

  • 注释三: 判断Action为: Intent.ACTION_MAIN, Category为Intent.CATEGORY_HOME的应用程序是否已开启

  • 注释四: 若未开启则开启该应用程序, 而符合上述要求的程序就是Launcher

    boolean startHomeActivityLocked(int userId, String reason) {
	// 判断工厂模式和mTopAction的值, 不符合要求直接退出
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) { // 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
            return false;
        }
	// 创建Launcher启动所需的Intent
        Intent intent = getHomeIntent(); // 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));

            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);

            if (app == null || app.instr == null) { // 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                // For ANR debugging to verify if the user activity is the one that actually
                // launched.
                final String myReason = reason + ":" + userId + ":" + resolvedUserId;
		// 启动Launcher
                mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason); // 44444444444444444444444444444444444444444444444444444444444444444444444444444444
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
        }

        return true;
    }

getHomeIntent()

路径: /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

startHomeActivityLocked()​注释二处获取Intent的函数

逻辑:

  • 创建Intent对象

    • 传入mTopAction = Intent.ACTION_MAIN
    • 传入mTopData
  • 设置Category

    • 值 = Intent.CATEGORY_HOME
  • 返回Intent对象

    Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

Launcher的AndroidManifest.xml文件

路径: /packages/apps/Launcher3/AndroidManifest.xml

  • 查看activity的子标签

    • intent-filter标签

                  <intent-filter>
                      <action android:name="android.intent.action.MAIN" />
                      <category android:name="android.intent.category.HOME" />
                      <category android:name="android.intent.category.DEFAULT" />
                      <category android:name="android.intent.category.MONKEY"/>
                  </intent-filter>
      
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.launcher3">
    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>

    .....

    <application
        android:backupAgent="com.android.launcher3.LauncherBackupAgent"
        android:fullBackupOnly="true"
        android:fullBackupContent="@xml/backupscheme"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher_home"
        android:label="@string/derived_app_name"
        android:theme="@style/LauncherTheme"
        android:largeHeap="@bool/config_largeHeap"
        android:restoreAnyVersion="true"
        android:supportsRtl="true" >

        <activity
            android:name="com.android.launcher3.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:windowSoftInputMode="adjustPan|stateUnchanged"
            android:screenOrientation="nosensor"
            android:configChanges="keyboard|keyboardHidden|navigation"
            android:resizeableActivity="true"
            android:resumeWhilePausing="true"
            android:taskAffinity=""
            android:enabled="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>

        <!--
        The settings activity. When extending keep the intent filter present
        -->
        <activity
            android:name="com.android.launcher3.SettingsActivity"
            android:label="@string/settings_button_text"
            android:theme="@android:style/Theme.DeviceDefault.Settings"
            android:autoRemoveFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.APPLICATION_PREFERENCES" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

	........

    </application>
</manifest>

startHomeActivityLocked()

路径: /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

startHomeActivityLocked()​用于启动Launcher的方法

逻辑:

  • 调用Activity监管器的moveHomeStackTaskToTop()

    • 将Launcher放入HomeStack中
    • HomeStack是ActivityStackSupervisor中定义的用于存储Launcher的变量
  • 调用startActivityLocked()方法启动Launcher

    • 剩余过程与Activity的启动过程相似(第四章)
    • 进入Launcher的onCreate方法中
    void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
        mSupervisor.moveHomeStackTaskToTop(reason);
        mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
                null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
                null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
                null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
                null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
                0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
                false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
                null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
        if (mSupervisor.inResumeTopActivity) {
            // If we are in resume section already, home activity will be initialized, but not
            // resumed (to avoid recursive resume) and will stay that way until something pokes it
            // again. We need to schedule another resume.
            mSupervisor.scheduleResumeTopActivities();
        }
    }

Launcher中应用图标显示过程

该部分内容看书过了一遍, 不做笔记.

Android系统启动流程

整体流程

  • 启动电源以及系统启动

  • 引导程序BootLoader

  • Linux内核启动

  • init进程启动

    • 初始化和启动属性服务
    • 启动Zygote进程
  • Zygote进程启动

    • Native层fork了init进程, execve()启动了app_process64, 并命名为zygote进程
    • 根据pid删除了init的Server
    • 启动Java虚拟机并注册JNI
    • 利用虚拟机实现: Native层 -> Java框架层
    • 利用虚拟机启动了SystemServer进程
  • SystemServer进程启动

    • 启动Binder线程池
    • 启动SystemServiceManager
  • Launcher启动

整体流程图

029956643A5ECABB49F0F336FD05B1C6

原文

  • Android进阶解密 刘望舒