天天看點

Android系統源碼閱讀(14):Zygote和System程序的啟動Android系統源碼閱讀(14):Zygote和System程序的啟動

Android系統源碼閱讀(14):Zygote和System程序的啟動

再不學習我們就老了

0. Zygote有什麼卵用?

Zygote是程序孵化器,Android系統中其他服務程序都是拷貝于它。Zygote在設計模式中對應于

prototype

,這樣做的好處是可以通過拷貝Zygote來快速建立一個程序。

1. Zygote腳本啟動

在開機時,init程序會調用如下腳本啟動程序。

system/core/rootdir/init.zygote32_64.rc :

service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    socket zygote stream  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
           

service

表明該程序是作為一個服務來啟動的,

--start-system-server

指明了該程序啟動後,需要啟動system服務。該程序對應的端口權限660,名字為zygote,其它程序可以通過該端口和它進行通信。

1.1 init程序建立新的app_process

在init程序中,啟動service程序的過程如下。

system/core/init/init.cpp :

void service_start(struct service *svc, const char *dynamic_args)
    //...
    NOTICE("Starting service '%s'...\n", svc->name);
    //建立新程序
    pid_t pid = fork();
    //在建立的程序中
    if (pid == ) {
        struct socketinfo *si;
        struct svcenvinfo *ei;
        char tmp[];
        int fd, sz;
        //依次建立service中的socket
        for (si = svc->sockets; si; si = si->next) {
            int socket_type = (
                    !strcmp(si->type, "stream") ? SOCK_STREAM :
                        (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
            //建立socket
            int s = create_socket(si->name, socket_type,
                                  si->perm, si->uid, si->gid, si->socketcon ?: scon);
            if (s >= ) {
                //釋出socket
                publish_socket(si->name, s);
            }
        }

    //...
    //将參數拷貝進svc結構體中
        if (!dynamic_args) {
            //沒有參數的情況
            //svc->args[0]對應于/system/bin/app_process32
            //下一步會加載該程式,并且傳入參數
            if (execve(svc->args[], (char**) svc->args, (char**) ENV) < ) {
                ERROR("cannot execve('%s'): %s\n", svc->args[], strerror(errno));
            }
        } else {
            char *arg_ptrs[INIT_PARSER_MAXARGS+];
            int arg_idx = svc->nargs;
            char *tmp = strdup(dynamic_args);
            char *next = tmp;
            char *bword;

            /* Copy the static arguments */
            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));

            while((bword = strsep(&next, " "))) {
                arg_ptrs[arg_idx++] = bword;
                if (arg_idx == INIT_PARSER_MAXARGS)
                    break;
            }
            arg_ptrs[arg_idx] = NULL;
            execve(svc->args[], (char**) arg_ptrs, (char**) ENV);
        }
        _exit();
    }
    //...
}
           

1.2 socket建立和釋出

下面主要分析一下

create_socket

publish_socket

兩個函數,來說明zygote的socket如何建立的。

建立socket。

system/core/init/util.cpp :

/*
 * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR
 * ("/dev/socket") as dictated in init.rc. This socket is inherited by the
 * daemon. We communicate the file descriptor's value via the environment
 * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
 */
int create_socket(const char *name, int type, mode_t perm, uid_t uid,
                  gid_t gid, const char *socketcon)
{
    struct sockaddr_un addr;
    int fd, ret;
    char *filecon;

    if (socketcon)
        setsockcreatecon(socketcon);
    //建立一個socket
    fd = socket(PF_UNIX, type, );
    if (fd < ) {
        ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
        return -;
    }

    if (socketcon)
        setsockcreatecon(NULL);

    //建立一個socket位址addr
    memset(&addr,  , sizeof(addr));
    addr.sun_family = AF_UNIX;
    //設定位址的檔案位置,這裡就是/dev/socket/zygote
    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
             name);

    ret = unlink(addr.sun_path);
    if (ret !=  && errno != ENOENT) {
        ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno));
        goto out_close;
    }

    filecon = NULL;
    if (sehandle) {
        ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK);
        if (ret == )
            setfscreatecon(filecon);
    }

    //将想要存儲socket的檔案位址addr和socket檔案描述符fd綁定起來
    ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
    if (ret) {
        ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
        goto out_unlink;
    }

    setfscreatecon(NULL);
    freecon(filecon);

    //設定使用者組root system
    chown(addr.sun_path, uid, gid);
    //設定權限660
    chmod(addr.sun_path, perm);

    INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
         addr.sun_path, perm, uid, gid);

    return fd;

out_unlink:
    unlink(addr.sun_path);
out_close:
    close(fd);
    return -;
}
           

釋出socket。

static void publish_socket(const char *name, int fd)
{    
    //字首為ANDROID_SOCKET_
    char key[] = ANDROID_SOCKET_ENV_PREFIX;
    char val[];
    //拼接出key
    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - ,
            name,
            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
    //将fd寫入val
    snprintf(val, sizeof(val), "%d", fd);
    //将key,value寫入環境變量中,以便其他程序通路
    add_environment(key, val);

    /* make sure we don't close-on-exec */
    fcntl(fd, F_SETFD, );
}
           

2. Zygote程序啟動過程

Zygote 程序的啟動從app_process的main函數開始。

Android系統源碼閱讀(14):Zygote和System程式的啟動Android系統源碼閱讀(14):Zygote和System程式的啟動

2.1 app_process.main

判斷需要啟動的程序的種類。

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

int main(int argc, char* const argv[])
{
    //針對舊核心做的處理...

    //建立AppRuntime對象
    AppRuntime runtime(argv[], 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 = ; i < argc; i++) {
        if (argv[i][] != '-') {
            break;
        }
        if (argv[i][] == '-' && argv[i][] == ) {
            ++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") == ) {
        //這裡是Zygote程序
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == ) {
            //同時需要開啟SystemServer
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == ) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", ) == ) {
            niceName.setTo(arg + );
        } else if (strncmp(arg, "--", ) != ) {
            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);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
        //作為參數傳遞給Zygote程序
            args.add(String8("start-system-server"));
        }

    //... 

        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()) {
    //這裡程序名字就是zygote
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    if (zygote) {
        //啟動Zygote,接下來會主要分析start函數
        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 ;
    }
}
           

2.2 AndroidRuntime.start

建立虛拟機,運作java函數。

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

/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    //建立一個虛拟機執行個體
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != ) {
        return;
    }
    onVmCreated(env);

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

    /*
     * 将參數轉化為java對象
     * 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() + , stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, , classNameStr);

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

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        //找到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 {
            //調用com.android.internal.os.ZygoteInit類的main函數
            //參數放在strArray裡
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 
            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() != )
        ALOGW("Warning: VM did not shut down cleanly\n");
}
           

2.3 ZygoteInit.main

frameworks/base/core/java/com/android/internal/os/Zygoteinit.java :

public static void main(String argv[]) {
        try {
            //解析參數
            RuntimeInit.enableDdms();
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            for (int i = ; 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.");
            }
            //注冊Socket,建立一個socket服務端
            registerZygoteSocket(socketName);
            //...

            // Do an initial gc to clean up after startup
            gcAndFinalize();

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

            if (startSystemServer) {
                //啟動系統服務
                startSystemServer(abiList, socketName);
            }

            Log.i(TAG, "Accepting command socket connections");
            //循環等待其他服務向zygote socket發送請求
            runSelectLoop(abiList);

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

2.4 ZygoteInit.registerZygoteSocket

建立了zygote socket的server端。

/**
     * Registers a server socket for zygote command connections
     *
     * @throws RuntimeException when open fails
     */
    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            //拼接出socket名稱ANDROID_SOCKET_zygote
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                //環境變量中在上面存儲了該key下對應的value
                String env = System.getenv(fullSocketName);
                //擷取socket的檔案描述符
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                //建立socket server,并且保留在一個靜态變量sServerSocket中
                sServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }
           

2.5 ZygoteInit.startSystemServer

從zygote中fork一個新的程序來單獨處理system server。

/**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
    //...
        /* Hardcoded command line to start the system server */
        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",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer", //這就是System server的類名
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
            //從zygote中fork出一個程序
            /* Request to fork the system server process */
            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 == ) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //在子程序中啟動System server,在第3節中詳細分析
            handleSystemServerProcess(parsedArgs);
        }
    //父程序傳回
        return true;
    }
           

2.6 ZygoteInit.runSelectLoop

Zygote啟動無限循環,等待請求。

/**
     * 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<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    //一個zygote socket檔案描述符
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);

        while (true) {
        //将現有的fd先存入pollFds
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = ; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            //一次循環最多讓一個peer接入,但是可能會處理多個peer的請求
            for (int i = pollFds.length - ; i >= ; --i) {
                if ((pollFds[i].revents & POLLIN) == ) {
                    //是否有請求寫入,沒有就繼續
                    continue;
                }
                if (i == ) {
                    //有人在zygote上寫入請求,獲得該peer
                    //這一步隻是peer和zygote建立連接配接,peer還未發送具體請求
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    //将其加入檔案描述符fds中,該peer會向其對應的fd寫入請求
                    //這一步不會處理,因為該peer沒有在pollFds中
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    //有peer向其fd寫入請求,這裡開始處理這個請求,處理完畢後删除
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }
           

3. System程序的啟動

接着2.5,Zygote fork出一個新的程序來啟動System server。接下來看在這個新程序中如何啟動的System server。

Android系統源碼閱讀(14):Zygote和System程式的啟動Android系統源碼閱讀(14):Zygote和System程式的啟動

3.1 ZygoteInit.handleSystemServerProcess

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

/**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        //因為fork了Zygote的程序,是以會複制它的socket
        //SystemServer用不着這個socket,先關了再說
        closeServerSocket();

        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

    //設定程序名
        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }

    //擷取system server類的路徑
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
        }

        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + ];
                amendedArgs[] = "-cp";
                amendedArgs[] = systemServerClasspath;
                System.arraycopy(parsedArgs.remainingArgs, , amendedArgs, , parsedArgs.remainingArgs.length);
            }

            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * 進一步啟動System server
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }
           

3.2 RuntimeInit.zygoteInit

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java :

/**
     * 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.<p>
     *
     * Current recognized args:
     * <ul>
     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
     * </ul>
     *
     * @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();

        //做一些基本的初始化,比如時間、log等
        commonInit();
        //進入native部分,将來章節再講
        nativeZygoteInit();
        //進一步啟動system
        applicationInit(targetSdkVersion, argv, classLoader);
    }
           

3.3 RuntimeInit.applicationInit

這一步開始調用SystemServer的main函數。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java :

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        VMRuntime.getRuntime().setTargetHeapUtilization(f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        }

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    //啟動需要啟動的類的main函數,這裡就是com.android.server.SystemServer
        // Remaining arguments are passed to the start class's static main
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }
           

3.4 SystemServer.main

這裡直接new了一個SystemServer,然後調用它的run函數。

3.5 SystemService.run

這一步開始依次啟動各種service。

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

private void run() {
        //...
        //設定系統時間、語言等
        if (!SystemProperties.get("persist.sys.language").isEmpty()) {
            final String languageTag = Locale.getDefault().toLanguageTag();

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

    //... 
    //一些虛拟機記憶體,堆棧的設定

    //該線程就是主線程
        // Prepare the main looper thread (this thread).
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();

    //...
    //建立SystemServiceManager
        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

        // Start services.
        try {
        //開始依次啟動各種服務,下一節詳細解釋
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
          //...
        }
        //永遠的循環..
        // Loop forever.
        Looper.loop();
    }
           

3.6 各種service啟動

startBootstrapServices

這裡面啟動的服務有:

Installer

ActivityManagerService

PowerManagerService

LightsService

DisplayManagerService

PackageManagerService

SensorService

(非具體)。

這些service有的會建立自己獨立的ServiceThread,是HandlerThread的子類,它們有着自己的looper循環。

startService

函數将所有的service的啟動過程統一管理,抽象為注冊、啟動兩步驟。

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

/**
     * Starts the small tangle of critical services that are needed to get
     * the system off the ground.  These services have complex mutual dependencies
     * which is why we initialize them all in one place here.  Unless your service
     * is also entwined in these dependencies, it should be initialized in one of
     * the other functions.
     */
    private void startBootstrapServices() {
        // Wait for installd to finish starting up so that it has a chance to
        // create critical directories such as /data/user with the appropriate
        // permissions.  We need this to complete before we initialize other services.
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

        // Power manager needs to be started early because other services need it.
        // Native daemons may be watching for it to be registered so it must be ready
        // to handle incoming binder calls immediately (including being able to verify
        // the permissions for those calls).
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // Now that the power manager has been started, let the activity manager
        // initialize power management features.
        mActivityManagerService.initPowerManagement();

        // Manages LEDs and display backlight so we need it to bring up the display.
        mSystemServiceManager.startService(LightsService.class);

        // Display manager is needed to provide display metrics before package manager
        // starts up.
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        // We need the default display before we can initialize the package manager.
        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        // Only run "core" apps if we're encrypting the device.
        String cryptState = SystemProperties.get("vold.decrypt");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;
        }

        // Start the package manager.
        Slog.i(TAG, "Package Manager");
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();

        Slog.i(TAG, "User Service");
        ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());

        // Initialize attribute cache used to cache resources from packages.
        AttributeCache.init(mSystemContext);

        // Set up the Application instance for the system process and get started.
        mActivityManagerService.setSystemProcess();

        // The sensor service needs access to package manager service, app ops
        // service, and permissions service, therefore we start it after them.
        startSensorService();
    }
           

startCoreServices

這一步啟動的serivce有:BatteryService,UsageStatsService,WebViewUpdateService。

/**
     * Starts some essential services that are not tangled up in the bootstrap process.
     */
    private void startCoreServices() {
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);

        // Tracks application usage stats.
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        // Update after UsageStatsService is available, needed before performBootDexOpt.
        mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

        // Tracks whether the updatable WebView is in a ready state and watches for update installs.
        mSystemServiceManager.startService(WebViewUpdateService.class);
    }
           

startOtherService

這一步啟動service又多又雜,主要有如下這些,其它還有不再一一列舉。

AccountManagerService accountManager = null;
        ContentService contentService = null;
        VibratorService vibrator = null;
        IAlarmManager alarm = null;
        IMountService mountService = null;
        NetworkManagementService networkManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        ConnectivityService connectivity = null;
        NetworkScoreService networkScore = null;
        NsdService serviceDiscovery= null;
        WindowManagerService wm = null;
        UsbService usb = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        CommonTimeManagementService commonTimeMgmtService = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        AudioService audioService = null;
        MmsServiceBroker mmsService = null;
        EntropyMixer entropyMixer = null;
        CameraService cameraService = null;
           

4. 總結

寫到這裡,有點淩亂,太多的程序和線程在這一過程中被建立。我用下圖來梳理這部分程序之間的關系,希望讓你一目了然吧。

Android系統源碼閱讀(14):Zygote和System程式的啟動Android系統源碼閱讀(14):Zygote和System程式的啟動