Android系统启动流程,从init.rc 到 launcher 加载过程分析

Android系统启动流程,从init.rc 到 launcher 启动过程分析

目录

1、zygote 启动分析

1.1、init进程的入口函数

1.2、解析init.rc

1.3、app_main.cpp 解析zygote启动参数

1.4、ZygoteInit.java 进入Java的地盘

1.5、Zygote进程启动总结:

2、启动systemServer

2.1、systemServer 简介

2.2、启动SystemServer进程的子进程

2.3、SystemServer 启动总结

3、启动Launcher

3.1、Launcher 启动总结:

4、参考


1、zygote 启动分析

1.1、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);
    }

    umask(0);

    add_environment("PATH", _PATH_DEFPATH);
    
    bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);

    // 1、创建挂载系统运行所需的目录
    if (is_first_stage) {
        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));
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
    }
    ...

    // 2、初始化kernel 打印的日志。
    InitKernelLogging(argv);
    
    ...
    // 3、系统属性服务初始化
    property_init();

    ...
    // 4、创建epoll句柄
    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(ERROR) << "epoll_create1 failed";
        exit(1);
    }
    
    // 5、用于设置处理子进程处理函的数,如果其子进程(zygote) 异常退出,
    // init进程会调用改函数中设定的信号处理函数来处理。
    signal_handler_init();
    
    // 6、导入默认的环境变量
    property_load_boot_defaults();
    export_oem_lock_status();

    // 7、启动属性服务
    start_property_service();

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

    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service",std::make_unique());
    parser.AddSectionParser("on", std::make_unique());
    parser.AddSectionParser("import", std::make_unique());

    // 8、解析init.rc 文件
    parser.ParseConfig("/init.rc");

    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(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 = property_get("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) {
        if (!waiting_for_exec) {
            am.ExecuteOneCommand();
            // 9、重启已经 死去 的进程
            restart_processes();
        }

        int timeout = -1;
        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (am.HasMoreCommands()) {
            timeout = 0;
        }

        bootchart_sample(&timeout);

        epoll_event ev;
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
        if (nr == -1) {
            PLOG(ERROR) << "epoll_wait failed";
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();
        }
    }

    return 0;
}

1、创建挂在文系统运行的时候所需要的文件目录,在系统不存在的时候这些目录也会不存在。

2、初始化Kernel 的 log,这样就可以从外界获取Kernel 的日志。 让kernel 和外界进行交流了。

3、对系统属性进行初始化。

  • 这个系统属性服务在android 系统中,为统一管理系统的属性,设计了一个统一的属性系统。每个属性都有一个名称和          值,他们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性。

 4、epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次.

5、用于设置处理子进程处理函的数,如果其子进程(zygote) 异常退出,init进程会调用改函数中设定的信号处理函数来处理。

6、导入默认的环境变量

7、启动属性服务

8、启动解析init.rc 服务

9、init 的所有子进程(zygote 和 其他的子进程)如果 死掉了,都是会在这里进行重启。

 

1.2、解析init.rc

system/core/rootdir/init.rc

init.rc是一个非常重要的文件,它是有Android 初始化语言(Android init Language)编写的脚本。主要包含5中类型语句:

  • Action
  • Command
  • Service
  • Option
  • Import
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

on early-init
    write /proc/1/oom_score_adj -1000
    write /proc/sys/kernel/sysrq 0
    restorecon /adb_keys
    mkdir /mnt 0775 root system
    restorecon /postinstall
    start ueventd

on init
    sysclktz 0

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

    ...

 其中这里的

  • import /init.${ro.zygote}.rc         这里导入和硬件平台相关的zygote

        Android系统启动流程,从init.rc 到 launcher 加载过程分析_第1张图片

 

  1. init.zygote32.rc         表示纯支持32位程序。
  2. init.zygote32_64.rc   表示支持32位程序,也支持64位程序。
  3. init.zygote64             表示纯支持64位的程序。
  4. init.zygote64_32.rc    表示支持64 位程序,也支持32位程序。

其中以 init.zygote32_64.rc 内容如下:

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

service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    priority -20
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks

可以看出启动了两个service 一个名称为zygote ,执行app_process32,作为主模式。

另一个名称为zygote_secondary,执行app_process64 ,作为辅助模式。

以 init.zygote64.rc 为例进行分析学习:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks
  1. 可以看到启动的这个service 的程序路径是 /system/bin/app_process64。
  2. 后面的即为启动这个service所传递的参数。
  3. class main 指的是zygote 的 classname 为 main

     Zygote是以service配置的,所以当解析该完成时,init进程就会调用fork去创建Zygote进程,并且执行app_main.cpp文件中的main函数,作为Zygote进行的启动入口。

1.3、app_main.cpp 解析zygote启动参数

frameworks\base\cmds\app_process\app_main.cpp

int main(int argc, char* const argv[])
{
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
        // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
        // EINVAL. Don't die on such kernels.
        if (errno != EINVAL) {
            LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
            return 12;
        }
    }
     
    // 1、创建AppRuntime 对象
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.

    int i;
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(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 = 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;
        }
    }

    Vector 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);
    } 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()) {
        const char* procName = niceName.string();
        pthread_setname_np(pthread_self(), procName);
        runtime.setArgv0(procName);
    }

    if (zygote) {
        // 调用start 启动zygoteInit
        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.");
        return 10;
    }
}

1、该函数首先创建一个AppRuntime对象。

2、然后对init.rc配置文件中的启动参数argc、argv[]进行解析。while循环中我们可以看到,

  • 如果配置的启动参数为--zygote,表示要启动Zygote进程。
  • 如果为--start-system-server表示要启动SystemServer进程。
  • 如果为--application就表示是普通的应用进程。
  • 我们当前的场景中就是第一个,参数解析完成后,此时的局部变量zygote的值为true。

3、最后的if/else分支就会执行runtime.start("com.android.internal.os.ZygoteInit", args, zygote) 来继续完成Zygote进行的启动。

其中AppRuntime 也是在该类中定义的:

class AppRuntime : public AndroidRuntime
{
public:
    AppRuntime(char* argBlockStart, const size_t argBlockLength)
        : AndroidRuntime(argBlockStart, argBlockLength)
        , mClass(NULL)
    {
    }

    void setClassNameAndArgs(const String8& className, int argc, char * const *argv) {
        mClassName = className;
        for (int i = 0; i < argc; ++i) {
             mArgs.add(String8(argv[i]));
        }
    }

    virtual void onVmCreated(JNIEnv* env)
    {
        if (mClassName.isEmpty()) {
            return; // Zygote. Nothing to do here.
        }

        /*
         * This is a little awkward because the JNI FindClass call uses the
         * class loader associated with the native method we're executing in.
         * If called in onStarted (from RuntimeInit.finishInit because we're
         * launching "am", for example), FindClass would see that we're calling
         * from a boot class' native method, and so wouldn't look for the class
         * we're trying to look up in CLASSPATH. Unfortunately it needs to,
         * because the "am" classes are not boot classes.
         *
         * The easiest fix is to call FindClass here, early on before we start
         * executing boot class Java code and thereby deny ourselves access to
         * non-boot classes.
         */
        char* slashClassName = toSlashClassName(mClassName.string());
        mClass = env->FindClass(slashClassName);
        if (mClass == NULL) {
            ALOGE("ERROR: could not find class '%s'\n", mClassName.string());
        }
        free(slashClassName);

        mClass = reinterpret_cast(env->NewGlobalRef(mClass));
    }

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

        AndroidRuntime* ar = AndroidRuntime::getRuntime();
        ar->callMain(mClassName, mClass, mArgs);

        IPCThreadState::self()->stopProcess();
    }

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

    virtual void onExit(int code)
    {
        if (mClassName.isEmpty()) {
            // if zygote
            IPCThreadState::self()->stopProcess();
        }

        AndroidRuntime::onExit(code);
    }


    String8 mClassName;
    Vector mArgs;
    jclass mClass;
}

 可以看到,AppRuntime 是继承 AndroidRuntime

/*
 * 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".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

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

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    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);
    }

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

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

    /*
     * Register android functions.
     */
    // 2.为JVM 注册 JNI 方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    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);
    // 3.传递进来的第一个参数 "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);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    // 4.将 classNameStr 中的 . 替换为 /
    char* slashClassName = toSlashClassName(className);
    // 5.找到zygoteInit类
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        // 6.找到 zygoteInit 的 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 {
            // 7.通过jni 调用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");
}

 上述代码主要是:

  1. 启动了JVM
  2. 为JVM 注册了JNI 方法
  3. 解析参数,得到对应的类,执行这个java类中的main方法,从起就进入了java的世界!

1.4、ZygoteInit.java 进入Java的地盘

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

public static void main(String argv[]) {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
            RuntimeInit.enableDdms();
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            // 1、解析从init.rc 文件中传递过来的参数是否启动system-server,并设置器对应
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = 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.");
            }
            // 2.注册zygoteSocket,这个socket 的名称是在 zygote
            registerZygoteSocket(socketName);
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            // 3.预加载类和资源
            preload();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

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

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

            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            // 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();
            
            // 4.启动systemServer
            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }
            
            Log.i(TAG, "Accepting command socket connections");
            // 5.启动Loop 来处理AMS 来创建应用进行处理。
            runSelectLoop(abiList);

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

 zygoteinit.java 主要做了如下几件事情

  1. 创建server端的Socket,名称为 ANDROID_SOCKET_zygote。
  2. 预加载类和系统资源
  3. 启动systemServer
  4. runSelectLoop 用于等待 后续 AMS 创建新的应用进程,和其进行通信.

1.创建 serverSocket 来看一下具体实现:

    /**
     * Registers a server socket for zygote command connections
     *
     * @throws RuntimeException when open fails
     */
    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            // 1.拼接socket 名称
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try { 
                // 2.获取socket 环境变量的值
                String env = System.getenv(fullSocketName);
                // 3.得到sockt 环境变量的值,并将其转为文件描述符参数
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                // 4.创建文件描述符
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                // 5.用这个文件描述法作为参数 创建LocalServerSocket
                sServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

        使用JNI 获取的环境变量的文件描述符参数来创建文件描述符,并将此描述符用于创建本地的serverSocket。在Zygote进程将SystemServer启动之后,就会在这个服务端等待AMS 来请求zygote进程来创建一个新的应用进程。

   2. 加载类和资源,有PreloadClasses,PreloadResources,PreloadOpenGL,这几项的加载在android 启动中占据了大约4秒钟的事件,这里其实可以进行加载优化,将这些穿行的加载做成线程池,放在线程池中加载,启动的事件会大大缩短。

  3.启动 systemService:

/**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_BLOCK_SUSPEND,
            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_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Hardcoded command line to start the system server */
        // 1.创建数组保存systemServer 启动的参数 
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,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);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            // 2.从当前(zygote)进程中fork 出一个子进程(就是当前的systemServer进程)
            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);
            }
            // 3.处理这个刚刚出生的systemserver子进程的后续事情
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

这里启动systemserver 主要是 像细胞分裂一样,从 zygote进程 fork出一个systemserver 进程来,这样就启动了systemserver,这样子这个server就有了父进程(zygote)的所有的资源。

4.runSelectLoop,等待AMS 来请求建立连接,或者请求创建应用程序进程

 /**
     * Runs the zygote process's select loop. Accepts new connections as
     * they happen, and reads commands from connections one spawn-request's
     * worth at a time.
     *
     * @throws MethodAndArgsCaller in a child process when a main() should
     * be executed.
     */
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList fds = new ArrayList();
        ArrayList peers = new ArrayList();
        // 1.拿到服务端的socket文件描述符 
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);
        // 2.就在这里傻傻的等着来AMS的连接请求
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
                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);
            }
            // 3
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    // 4
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        // 5 
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

在注释2.处无限等待AMS 的连接请求或者创建应用程序进程

在注释3:将fds 中的数据转移到pollFds中

在注释4:如果i==0 说明服务器和AMS 连接上了。通过acceptCommandPeer 来得到这个ZygoteConnection 并添加到socket 连接列表peers 中。以便可以接收到AMS 发过来的请求。 如果 i != 0 说明是AMS 向 zygote 发送了请求创建一个应用进程,如果创建成功,就把这个连接从socket 连接表和 文件描述符中移除。

zygote 启动过程至此就告一段落了。

1.5、Zygote进程启动总结:

zygote 启动做了如下几件事情

  1. 创建AppRuntime 并调用start 方法启动Zygote进程。
  2. 创建JVM,并为其注册JNI方法
  3. 通过JNI 调用ZygoteInit.java 从C/C++ 进入了java的地盘
  4. 通过 zygote进程fork  systemServer 来创建服务端 socket,并通过这个服务端socket 监听和AMS  的连接或者监听AMS 请求创建一个应用程序进程。
  5. 启动SystemServer

2、启动systemServer

2.1、systemServer 简介

SystemServer 用来创建其他service ,并管理创建的service 。例如:AMS、WMS、PMS等都是由他来创建的,下面来看下如何启动这个 父进程。

startSystemServer方法最终有一句 handleSystemServerProcess() 方法

/**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        // 子类不需要zygote进程的 serverSocket
        closeServerSocket();
        ...
        if (parsedArgs.invokeWith != null) {
           ...
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                // 1.创建 PathClassLoader
                cl = createSystemServerClassLoader(systemServerClasspath,
                                                   parsedArgs.targetSdkVersion);

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

            // 2. 调用zygote的zygoteInit方法
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }
    }

最终调用 “RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);” 方法继续执行。

   /**
     * The main function called when started through the zygote process. This
     * could be unified with main(), if the native code in nativeFinishInit()
     * were rationalized with Zygote startup.

* * Current recognized args: *

    *
  • [--] <start class name> <args> *
* * @param targetSdkVersion target SDK version * @param argv arg strings */ public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); redirectLogStreams(); commonInit(); // 1.启动binder 线程池 nativeZygoteInit(); // 2.进入systemServer 的main方法 applicationInit(targetSdkVersion, argv, classLoader); }

在注释1 调用的nativeZygoteInit()是个JNI函数,启动了大名鼎鼎的Binder线程池

在注释2 进入了系统的SystemServer 的main方法。

分别学习一下

注释1:启动binder线程池,在AndroidRuntime.cpp文件中可以看到

\frameworks\base\core\jni\AndroidRuntime.cpp

/*
 * JNI registration.
 */
static const JNINativeMethod gMethods[] = {
    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};


static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}
    /**
     * This gets called after the JavaVM has initialized after a Zygote
     * fork. Override it to initialize threads, etc. Upon return, the
     * correct static main will be invoked.
     */
    virtual void onZygoteInit() { }

点进去之后实现为空,注释说 Override it to initialize threads ,那就找下子类的实现。不过实际调用的onZygoteInit()应该是AndroidRuntime的子类AppRuntime的:

frameworks/base/cmds/app_process/app_main.cpp

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

里面构造了进程的ProcessState全局对象,而且启动了线程池。

ProcessState对象是典型的单例模式,它的self()函数如下:

sp ProcessState::self()  
{  
    Mutex::Autolock _l(gProcessMutex);  
    if (gProcess != NULL) {  
        return gProcess;  
    }  
    gProcess = new ProcessState;  
    return gProcess;  
}  

ProcessState对于Binder通信机制而言非常重要,现在system server进程的PrecessState算是初始化完毕了。启动了binder线程池。

注释2 :用于进入systemServer 的main方法。

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        ...

        invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class cl;

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

        Method m;
        try {
            // 2.找到systemServer 的main方法
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        // 3.找到main的方法传入MethodAndArgsCaller,抛出异常。
        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

注释1 处通过反射拿到SystemServer类,并在注释2处找打这个类的main,在注释3 处抛出异常。这个MethodAndArgsCaller异常。

捕获这个异常的地方在ZygoteInit的main方法中,这个main方法会调用systemServer 的main方法。这个异常的定义是在zygoteInit.java 中定义的

/**
     * Helper exception class which holds a method and arguments and
     * can call them. This is used as part of a trampoline to get rid of
     * the initial process setup stack frames.
     */
    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 {
                // 1.代用main 方法
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);

                ...
            }
        }
    }

在注释1 mMethed 方法就是 SystemServer 的 main 方法,启动这个main 方法就进入 systemServer 的 main 中。

2.2、启动SystemServer进程的子进程

frameworks\base\services\java\com\android\server\SystemServer.java

public static void main(String[] args) {
    new SystemServer().run();
}


private void run() {
        try {
            ...
            Looper.prepareMainLooper();

            // Initialize native services.
            // 1.加载这个so 文件,初始化native service
            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.
            // 2.初始化系统的Context
            createSystemContext();

            // Create the system service manager.
            // 3. 创建一个SystemServiceManager
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        // Start services.
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            // 4.启动引导服务
            startBootstrapServices();
            // 5.启动核心服务
            startCoreServices();
            // 6. 启动其他服务
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        ...

        // Loop forever.
        Looper.loop();
        ...
    }
  • 注释1. 加载 libandroid_servers.so 库。
  • 注释2. 初始化系统的Context
  • 注释3. 创建SystemServiceManager,他会对系统的service进行管理(启动,创建,生命周期) 
  • 注释4. 启动引导服务。会使用SystemServiceManager 启动了ActivityServiceManager、PowerManagerService、PackageManagerService 等服务。
  • 注释5. 启动核心服务,包括BatteryService、UsageStatsService、WebViewUpdateService
  • 注释6. 启动其他服务 包括CameraService、AudioService、UsbService、WindowManagerService、VibratorService...这些服务是非紧要和不用立即启动的优先级较低的服务。

这些服务启动逻辑都比较相似。以PowerManagerService 为例:

public  T startService(Class serviceClass) {
	try {
		final String name = serviceClass.getName();
		...

		// 1.Register it.
		mServices.add(service);

		// 2.Start it.
		try {
			service.onStart();
		} catch (RuntimeException ex) {
			throw new RuntimeException("Failed to start service " + name
					+ ": onStart threw an exception", ex);
		}
		return service;
	} finally {
		Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
	}
}

启动service 首先在 注释1 处将这个service 加入到systemService ( private final ArrayList mServices = new ArrayList();)这样就完成了PowerManagerService 的注册工作。注释2调用 PowerManagerService.onStart启动了这个服务。

除了这样启动服务以外,还可以直接调用的main 方法来启动,以PackageManagerService为例:

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


public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        ServiceManager.addService("package", m);
        return m;
    }

直接创建完对应的服务,然后注册到ServiceManager中,通过这个ServiceManager 来管理创建的服务。用于系统的binder通信,客户端使用的时候通过注册服务,进行信息查询,根据信息与services所在的server进程监理通路,才Client可以使用。

2.3、SystemServer 启动总结

  • systemServer进程被创建后,主要做了如下工作:
  • 启动binder线程池,这样可以与其他进程通信
  • 创建SystemServiceManager ,用于对service的管理
  • 启动各种服务

3、启动Launcher

在加载完成SystemServer之后,对系统的各种server进行管理。启动Launcher 的入口为AMS 的 systemReady 方法,它在SystemServer 的 startOtherServices 方法中被调用。如下所示:

frameworks\base\services\java\com\android\server\SystemServer.java


    /**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored
     * and organized.
     */
    private void startOtherServices() {
        ...
        mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                Slog.i(TAG, "Making services ready");
                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_ACTIVITY_MANAGER_READY);
                
                ...
            }
        });
    }

然后再AMS 中查看SystemReady 方法如下:

public void systemReady(final Runnable goingCallback) {
        ...
        // Start up initial activity.
        mBooting = true;
        startHomeActivityLocked(mCurrentUserId, "systemReady");
        ...
    }

从这里看到系统的注释 stat up initial activity .这样一个默认的activity就是我们的homeActivity。launcher 桌面

boolean startHomeActivityLocked(int userId, String reason) {
        // 1 
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            // We are running in factory test mode, but unable to find
            // the factory test app, so just sit around displaying the
            // error message and don't try to start anything.
            return false;
        }

        // 2 获取homeIntent
        Intent intent = getHomeIntent();
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            // 3.设置对intent进行判断
            if (app == null || app.instrumentationClass == null) {
                // 4. 设置intent 的一些标志位,并启动launcher
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                mStackSupervisor.startHomeActivity(intent, aInfo, reason);
            }
        }

        return true;
    }

注释1处的mFactoryTest代表系统的运行模式,系统的运行模式分为三种,分别是非工厂模式、低级工厂模式和高级工厂模式,mTopAction则用来描述第一个被启动Activity组件的Action,它的值为Intent.ACTION_MAIN。因此注释1的代码意思就是mFactoryTest为FactoryTest.FACTORY_TEST_LOW_LEVEL(低级工厂模式)并且mTopAction=null时,直接返回false,然后是调用getHomeIntent()方法。

注释2的 代码处获取Intent ,代码如下

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

创建Intent ,并将mTopAction(String mTopAction = Intent.ACTION_MAIN;) 和 mTopData 传入。设置 setComponent 的值 为mTopComponent = new ComponentName(app.packageName, ai.name); 为包名(Name of the package that this item is in) 和 app 名称 (Public name of this item. From the "android:name" attribute.),如果系统运行非低级工程模式,则 addCategory 为 Intent.CATEGORY_HOME 最后返回改intent。

我们再回到ActivityManagerService的startHomeActivityLocked函数,假设系统的运行模式不是低级工厂模式,在注释3处判断符合Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME的应用程序是否已经启动,如果没启动则调用注释4的方法启动该应用程序。这个应用程序就是launcher。因为launcher 的AndroidManifest文件中的intent-filter标签匹配了Action 为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME。

Launcher 的 AndroidManifest文件如下所示:

packages\apps\Launcher3\AndroidManifest.xml


            
                
                
                
                
            
        

经历了一系列的方法后就进入了 startHomeActivity 方法。

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
        // 1. 将Home任务排到栈顶
        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
        // 2.启动Activity
        startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo,
                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 */,
                null /* outActivity */, null /* container */,  null /* inTask */);
        if (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.
            // 3.刚好如果已在Home了,那就直接前置
            scheduleResumeTopActivities();
        }
    }


3.1、Launcher 启动总结:

  1. SystemServer启动完所有Boot服务,Core服务、Other服务,就通知所有服务systemReady()
  2. 其中在AMS的systemReady()里就做了启动Launcher
  3. 创建 Launcher 的 Intent ,并通过各种判断最终启动Launcher.

4、参考

Android系统启动后Launcher启动(概述)

Android Framework学习(四)之Launcher启动流程解析

Android系统启动流程(四)Launcher启动过程与系统启动流程

 

 

你可能感兴趣的:(init.rc,android,zygote,systemserver,launcher)