Android系統(tǒng)啟動過程分析

主要流程

簡化流程圖

init進(jìn)程啟動過程

init進(jìn)程是Android系統(tǒng)中用戶空間的第一個進(jìn)程纪铺。進(jìn)程號為1颜价。

引入init進(jìn)程

第一步

當(dāng)電源按下時引導(dǎo)芯片代碼從預(yù)定的地方(固化為ROM中)開始執(zhí)行悼瘾。加載引導(dǎo)程序BootLoaderRAM中執(zhí)行。

第二步

BootLoader是在Android操作系統(tǒng)開始運行前的一個小程序齿诞,主要作用是把系統(tǒng)OS拉起來運行麻裳。

第三步

當(dāng)內(nèi)核完成系統(tǒng)設(shè)置后,在系統(tǒng)文件中尋找init.rc文件涨椒,并啟動init進(jìn)程摊鸡。

啟動init進(jìn)程就會執(zhí)行它的入口函數(shù)main,文件路徑為:system/core/init/init.cpp

int main(int argc, char** argv) {
    ......
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();
        umask(0);
        //創(chuàng)建和掛載啟動所需要的文件目錄
        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));
        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));
        ......
    }
    ......
    //對屬性服務(wù)進(jìn)行初始化
    property_init();
    ......

    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(ERROR) << "epoll_create1 failed";
        exit(1);
    }
    //用于設(shè)置子進(jìn)程信號處理函數(shù)蚕冬,如果子進(jìn)程異常退出免猾,init進(jìn)程會調(diào)用該函 
    //數(shù)中設(shè)置的信號處理函數(shù)進(jìn)行處理。
    signal_handler_init();
    ......
    //啟動屬性服務(wù)
    start_property_service();
    ......
    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"));
    } 
    ......
    while (true) {
        ......
        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
            //重啟死去的服務(wù)
            restart_processes();
        }
        ......
    }
    return 0;
}

從上述代碼中可以看出播瞳,init進(jìn)程主要做了三件事:

  • 創(chuàng)建和掛載啟動所需的文件目錄掸刊。

啟動掛載了tmpfs、devpts赢乓、proc忧侧、sysfs和selinuxfs共5種文件系統(tǒng),這些是系統(tǒng)運行時目錄牌芋,也就是說只有在系統(tǒng)運行的時候才會存在蚓炬。

  • 初始化和啟動屬性服務(wù)。

屬性服務(wù)類似Windows平臺上的注冊表管理器躺屁,注冊表中以key-value的形式來記錄用戶肯夏、軟件的一些使用信息。即使系統(tǒng)或軟件重啟犀暑,也能夠根據(jù)之前注冊表中的記錄驯击,進(jìn)行相應(yīng)的初始化工作。

  • 解析init.rc文件耐亏,創(chuàng)建Zygote進(jìn)程徊都。

該文件的路徑為:system/core/rootdir/init.rc。它是一個非常重要的配置文件广辰,是由Android初始化語言編寫的腳本暇矫。Android8.0對該文件進(jìn)行來拆分主之,每個服務(wù)對應(yīng)一個rc文件,啟動Zygote的腳本在init.zygoteXX.rc中定義李根,代表多少位處理器槽奕。這里以64位為例。

system/core/rootdir/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

這里我們只分析zygote進(jìn)程的創(chuàng)建房轿,所以只貼出了init.rc文件中的Serivice類型的語句粤攒,省略了其他語句;這是由Android初始化語言編寫的冀续。它的格式如下:
service <name> <pathname> [ <argument> ]* //名字 執(zhí)行程序路徑 傳遞參數(shù)
< option > //修飾詞琼讽,影響什么時候啟動,如何啟動service洪唐。
< option >
......
上面的代碼的含義就是:通知init進(jìn)程創(chuàng)建名為zygote的進(jìn)程,這個進(jìn)程的執(zhí)行路徑為:/system/bin/app/_process64吼蚁,其后面的代碼是傳遞給app_process64的參數(shù)凭需。class main指的是zygoteclassnamemain

init.rc中的Service類型的語句有相應(yīng)的類來進(jìn)行解析肝匆,Service語句采用ServiceParser來進(jìn)行解析粒蜈,該實現(xiàn)代碼在system/core/init/service.app中,代碼在這不再貼出旗国,大概的解析過程就是:根據(jù)參數(shù)創(chuàng)建出Service對象枯怖,然后根據(jù)選項域中的內(nèi)容填充Service對象,最后將該對象加入vector類型的Service鏈表中能曾。

init.rc中有如下代碼:

......
on nonencrypted
    class_start main
    class_start late_start
......

class_start是Android初始化語言中的Command類型的語句度硝,對應(yīng)的函數(shù)為do_class_start含義就是啟動classname為main的Service寿冕。蕊程,從上述代碼我們知道zygoteclassnamemain。

do_class_start函數(shù)是在system/core/bin/builtins.cpp中驼唱,代碼如下:

static int do_class_start(const std::vector<std::string>& args) {
    ServiceManager::GetInstance().
        ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
    return 0;
}

ForEachServiceInClass函數(shù)會遍歷Service鏈表藻茂,找到classnamemainZygote,并執(zhí)行StartIfNotDisabled ()函數(shù)玫恳。

StartIfNotDisabled ()函數(shù)的代碼是在system/core/init/service.cpp中定義的辨赐,代碼如下:

bool Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {
        return Start();
    } else {
        flags_ |= SVC_DISABLED_START;
    }
    return true;
}

如果Service沒有在其對應(yīng)的rc文件中設(shè)置disabled選項,就會執(zhí)行Start()函數(shù)京办,Zygote對應(yīng)的文件沒有設(shè)置disabled選項掀序。

Start()函數(shù):system/core/init/service.cpp

bool Service::Start() { 
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
    //如果已運行,直接返回
    if (flags_ & SVC_RUNNING) {
        return false;
    }
    ......
    struct stat sb;
    //判斷需要啟動的Service對應(yīng)的執(zhí)行文件是否存在臂港,存在才會執(zhí)行森枪。
    if (stat(args_[0].c_str(), &sb) == -1) {
        PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
        flags_ |= SVC_DISABLED;
        return false;
    }
    ......
    pid_t pid = -1;
    if (namespace_flags_) {
        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
    } else {
        //如果沒有啟動视搏,調(diào)用fork函數(shù)創(chuàng)建子進(jìn)程
        pid = fork();
    }

    if (pid == 0) {
        umask(077);
        ......
        //調(diào)用execve函數(shù),子進(jìn)程就會被啟動
        if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
            PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
        }
        _exit(127);
    }
    ......
    return true;
}

調(diào)用execve 函數(shù)县袱,子進(jìn)程就會被啟動浑娜,就是執(zhí)行對應(yīng)的main函數(shù)Zygote的執(zhí)行路徑為:system/bin/app_process64式散,對應(yīng)的文件為app_main.cpp筋遭。

frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
    ......
    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;
        }
    }
    ......
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

調(diào)用runtime.start函數(shù)就啟動了Zygote進(jìn)程

Zygote進(jìn)程

Android系統(tǒng)中暴拄,DVM和ART漓滔、應(yīng)用程序進(jìn)程以及運行系統(tǒng)的關(guān)鍵服務(wù)SystemServer進(jìn)程都是有Zygote進(jìn)程創(chuàng)建的,我們也稱它為孵化器乖篷。它通過fock(復(fù)制進(jìn)程)的形式來創(chuàng)建應(yīng)用程序進(jìn)程和SystemServer進(jìn)程响驴,由于Zygote進(jìn)程在啟動的時候會創(chuàng)建DVM或者ART,因此通過fock而創(chuàng)建的應(yīng)用程序進(jìn)程和SystemServer進(jìn)程可以在內(nèi)部獲取一個DVM或者ART的實例副本(也就是說一個Android應(yīng)用程序?qū)?yīng)這一個DVM或者ART)撕蔼。

Zygote進(jìn)程都是通過fock自身來創(chuàng)建子進(jìn)程的豁鲤,這樣Zygote進(jìn)程以及子進(jìn)程都會進(jìn)入app_main.cppmain函數(shù),所以在上述代碼中先區(qū)分來當(dāng)前運行在哪個進(jìn)程中鲸沮。運行Zygote進(jìn)程就會執(zhí)行AndroidRuntime.start函數(shù)琳骡。

frameworks/base/core/jni/AndroidRuntime.cpp代碼如下:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ......
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //啟動Java虛擬機(jī)
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    //為JVM注冊JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ......
    //從app_main傳過來的參數(shù)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);
    } else {
        //找到ZygoteInit的main函數(shù)
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {
            //通過JNI調(diào)用ZygoteInit的main函數(shù)
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

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

上述代碼最后會調(diào)用ZygoteInitmain方法,該方法是由Java語言編寫的讼溺,當(dāng)前的運行邏輯在Native中楣号,這就需要通過JNI來調(diào)用Java。這樣Zygote就從Native層近入了Java框架層怒坯。

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.javamain方法代碼如下:

public static void main(String argv[]) {
    ......
    try {
        ......
        //創(chuàng)建一個Server端的socket炫狱,socketName = “zygote”
       //在這個socket上會等待AMS的請求
        zygoteServer.registerServerSocket(socketName);
        if (!enableLazyPreload) {
            bootTimingsTraceLog.traceBegin("ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            //預(yù)加載類和資源
            preload(bootTimingsTraceLog);
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            bootTimingsTraceLog.traceEnd(); // ZygotePreload
        } else {
            Zygote.resetNicePriority();
        }
        //啟動SystemServer進(jìn)程
        if (startSystemServer) {
            startSystemServer(abiList, socketName, zygoteServer);
        }
        //等待AMS請求,里面是一個while(true)循環(huán)
        zygoteServer.runSelectLoop(abiList);
        zygoteServer.closeServerSocket();
    }......
}

該方法中主要做了4件事:
1.創(chuàng)建一個Server端的socket(LocalServerSocket)敬肚。
2.預(yù)加載類和資源毕荐。
3.啟動SystemServer進(jìn)程。
4.等待AMS請求創(chuàng)建新的應(yīng)用程序進(jìn)程艳馒。

從上面的代碼我們看出Zygote進(jìn)程主要做了如下幾件事情:

  • 1.創(chuàng)建Java虛擬機(jī)并為Java虛擬機(jī)注冊JNI方法憎亚。
  • 2.通過JNI調(diào)用ZygoteInitmain函數(shù)進(jìn)入Zygote的Java框架層。
  • 3.通過registerServerSocket 方法創(chuàng)建服務(wù)端Socket弄慰,并通過runSelectLoop 方法等待AMS的請求來創(chuàng)建新的應(yīng)用程序進(jìn)程第美。
  • 4.啟動SystemServer進(jìn)程。

SystemServer進(jìn)程

SystemServer進(jìn)程主要用于創(chuàng)建系統(tǒng)服務(wù)陆爽,AMS什往、WMS、PMS都是由它來創(chuàng)建的慌闭。從上面得知通過調(diào)用ZygoteInitstartSystemServer 方法來啟動SystemServer進(jìn)程别威,下面就看一下該方法的代碼:

private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
        throws Zygote.MethodAndArgsCaller, RuntimeException {
    ......
    //創(chuàng)建args數(shù)組躯舔,該數(shù)組用來保存啟動SystemServer的啟動參數(shù)
    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);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
        //創(chuàng)建一個子進(jìn)程,也就是SystemServer進(jìn)程
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
    //當(dāng)前代碼運行在子進(jìn)程中省古,也就是SystemServer進(jìn)程
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        //SystemServer進(jìn)程復(fù)制了Zygote進(jìn)程的地址空間粥庄,因此也會得到Zygote創(chuàng)建的Socket。
        //該Socket對SystemServer進(jìn)程沒有用豺妓,所以要關(guān)閉惜互。
        zygoteServer.closeServerSocket();
        //處理SystemServer進(jìn)程
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

從上面代碼可以看出,SystemServer進(jìn)程的用戶id和用戶組id被設(shè)置為1000琳拭,并且擁有1001~1010训堆、1018、1021白嘁、1032坑鱼、3001~3010的權(quán)限;進(jìn)程名字為system_server絮缅;啟動的類名為:com.android.server.SystemServer姑躲。

創(chuàng)建出SystemServer進(jìn)程之后就會在該進(jìn)程調(diào)用ZygoteInit.handleSystemServerProcess 方法,下面看一下該方法的代碼:

private static void handleSystemServerProcess(
        ZygoteConnection.Arguments parsedArgs)
        throws Zygote.MethodAndArgsCaller {
    ......
    if (parsedArgs.invokeWith != null) {
      ......
    } else {
        ClassLoader cl = null;
        if (systemServerClasspath != null) {
            //創(chuàng)建PathClassLoader
            cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
            Thread.currentThread().setContextClassLoader(cl);
        }
        //調(diào)用zygoteInit方法
        ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }
}

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();
    //執(zhí)行SystemServer的main方法
    RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

zygoteInit方法中創(chuàng)建了Binder線程池盟蚣,這樣SystemServer進(jìn)程就可以使用Binder于其他進(jìn)程進(jìn)行通信了。

創(chuàng)建Binder線程池后會調(diào)用RuntimeInit.applicationInit方法卖怜,下面就接著看下該方法的代碼:
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws Zygote.MethodAndArgsCaller {
    ......
    // Remaining arguments are passed to the start class's static main
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws Zygote.MethodAndArgsCaller {
    Class<?> cl;
    try {
        //通過反射得到SystemServer類
        cl = Class.forName(className, true, classLoader);
    }......
    Method m;
    try {
        //找到SystemServer的main方法
        m = cl.getMethod("main", new Class[] { String[].class });
    }......
    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    }
    /*
     * 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 Zygote.MethodAndArgsCaller(m, argv);
}

通過反射得到SystemServer屎开,className的值就是上面提到的com.android.server.SystemServer,然后再找到main方法马靠,最后將main方法傳入Zygote .MethodAndArgsCaller異常中并拋出該異常奄抽。捕獲該異常的代碼在ZygoteInit.main方法中,該main方法會調(diào)用SystemServermain方法甩鳄。

那為什么不直接在invokeStaticMain方法中調(diào)用呢逞度?而是在異常捕獲中調(diào)用?

原因是異常處理會清楚所有設(shè)置過程中需要的堆棧幀妙啃,讓SystemServermain方法看起來像是SystemServer進(jìn)程的入口档泽。(在Zygote
啟動SystemServer進(jìn)程之后,SystemServer進(jìn)程做了很多準(zhǔn)備工作揖赴,這些工作都是在main方法調(diào)用之前做的馆匿。)

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.javamain方法代碼:

public static void main(String argv[]) {
    ......
    try {
    ......
    //捕獲MethodAndArgsCaller異常
    } catch (Zygote.MethodAndArgsCaller caller) {
        caller.run();
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        zygoteServer.closeServerSocket();
        throw ex;
    }
}

在異常處理中直接調(diào)用Zygote.MethodAndArgsCallerrun方法,可以看出MethodAndArgsCallerZygote的靜態(tài)內(nèi)部類燥滑。

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

public static class MethodAndArgsCaller extends Exception
        implements Runnable {
    ......
    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }
    ......
    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        }......
    }
}

此處的mMethod就是SystemServermain方法渐北。

這樣就進(jìn)入了SystemServermain方法

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

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

private void run() {
    try {
        ......
        //創(chuàng)建Looper
        Looper.prepareMainLooper();
        //加載動態(tài)庫“l(fā)ibandroid_servers.so”
        System.loadLibrary("android_servers");
        performPendingShutdown();
        //創(chuàng)建系統(tǒng)的上下文Context
        createSystemContext();
        // 創(chuàng)建SystemServiceManager
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        SystemServerInitThreadPool.get();
    } finally {
        traceEnd();  // InitBeforeStartServices
    }
    // Start services.
    try {
        traceBeginAndSlog("StartServices");
        //啟動引導(dǎo)服務(wù)
        startBootstrapServices();
        //啟動核心服務(wù)
        startCoreServices();
        //啟動其他服務(wù)
        startOtherServices();
        SystemServerInitThreadPool.shutdown();
    }......
}

通過上面可以看出系統(tǒng)服務(wù)分為三種:
1.引導(dǎo)服務(wù)。
2.核心服務(wù)铭拧。
3.其他服務(wù)赃蛛。

private void startBootstrapServices() {
    ......
    Installer installer = mSystemServiceManager.startService(Installer.class);
    ......
    mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
    ......
   //需要注意的是 ActivityManagerService.Lifecycle實現(xiàn)了SystemService
    mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
    ......
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    ......
    //在該方法中會把ActivityManagerService添加到ServiceManager中
    mActivityManagerService.setSystemProcess();
    ......
}
private void startCoreServices() {
    ......
    mSystemServiceManager.startService(DropBoxManagerService.class);
    traceEnd();
    ......
    mSystemServiceManager.startService(BatteryService.class);
    ......
}
private void startOtherServices() {
    ......
    mSystemServiceManager.startService(KeyChainSystemService.class);
    ......
    mSystemServiceManager.startService(TelecomLoaderService.class);
    ......
}

部分服務(wù)表:

引導(dǎo)服務(wù) 作用
Installer 系統(tǒng)安裝APK時的一個服務(wù)恃锉,啟動完成Installer服務(wù)之后才能啟動其他的服務(wù)
ActivityManagerService 負(fù)責(zé)四大組件的啟動、切換和調(diào)度
PowerManagerService 計算系統(tǒng)中和Power相關(guān)的計算呕臂,然后決策系統(tǒng)應(yīng)該如何反應(yīng)
LightsService 管理和顯示背光LED
DisplayManagerService 用來管理所有顯示的設(shè)備
UserManagerService 多用戶模式管理
SensorService 為系統(tǒng)提供各種感應(yīng)器服務(wù)
PackageManagerService 用來對APK進(jìn)行安破托、解析、刪除诵闭、卸載等操作
...... .....
核心服務(wù)
DropBoxManagerService 用于生成和管理系統(tǒng)運行時的一些日志文件
BatteryService 管理電池相關(guān)的服務(wù)
UsageStatsService 收集用戶使用每一個app的頻率炼团、使用時長
WebViewUpdateService WebView更新服務(wù)
其他服務(wù)
CameraService 攝像頭相關(guān)服務(wù)
AlarmManagerService 全局定時器管理服務(wù)
InputManagerService 管理輸入事件
WindowManagerService 窗口管理服務(wù)
VrManagerService VR模式管理服務(wù)
BluetoothService 藍(lán)牙管理服務(wù)
NotificationManagerService 通知管理服務(wù)
DeviceStorageMonitorService 存儲相關(guān)管理服務(wù)
LocationManagerService 定位管理服務(wù)
AudioService 音頻相關(guān)管理服務(wù)
...... ......

我們從上面看出相關(guān)的服務(wù)一種是通過SystemServiceManagerstartService方法來啟動的;另一種是直接調(diào)用服務(wù)的main方法疏尿,比如:PackageManagerService瘟芝。下面分別看一下這兩種方式的代碼實現(xiàn):

/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

public class SystemServiceManager {
    ......
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
    ......
    //startService方法有幾個重載,最終都會調(diào)用該方法
    public void startService(@NonNull final SystemService service) {
        //注冊服務(wù)
        mServices.add(service);
        // Start it.
        long time = System.currentTimeMillis();
        try {
            //調(diào)用服務(wù)自身的onStart方法
            service.onStart();
        }......
    }
}
public abstract class SystemService {
    ......
}

先將服務(wù)添加到mService中褥琐,它是一個存儲SystemService類型的ArrayList锌俱,這樣就完成來該服務(wù)的注冊工作。然后調(diào)用服務(wù)自身的onStart()方法來啟動服務(wù)敌呈。由SystemServiceManager創(chuàng)建并啟動的服務(wù)贸宏,都是繼承了SystemService,但是并沒有實現(xiàn)IBinder磕洪,所以是不可以進(jìn)行Binder通信的吭练,也就是由它管理的服務(wù)是用于進(jìn)程內(nèi)部通信的。

/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub
        implements PackageSender {
    ......
    public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        PackageManagerServiceCompilerMapping.checkProperties();
        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        //注冊
        ServiceManager.addService("package", m);
        return m;
    }
    ......
}

創(chuàng)建對象后添加到ServiceManager中析显,它是用來管理系統(tǒng)中各種Service的鲫咽,由它管理的服務(wù)都實現(xiàn)了IBinder,所以在ServiceManager中注冊的服務(wù)是用于進(jìn)程間通信的:用于系統(tǒng)C/S架構(gòu)中的Binder通信機(jī)制谷异》质客戶端要使用某個Service,需要先到ServiceManager中查詢Service的信息歹嘹,然后根據(jù)該信息與Service所在的Server進(jìn)程建立通信箩绍,這樣客戶端就可以使用Service了。

從上面的代碼我們看出SystemServer進(jìn)程主要做了如下幾件事情:

  • 1.啟動Binder線程池尺上,這樣就可以與其他進(jìn)程進(jìn)行通信了材蛛。
  • 2.創(chuàng)建SystemServiceManager,用于對系統(tǒng)其他服務(wù)進(jìn)行創(chuàng)建尖昏、啟動和聲明周期管理仰税。
  • 3.啟動各種系統(tǒng)服務(wù)。

SystemServer進(jìn)程Zygote進(jìn)程fork的第一個進(jìn)程抽诉。其中WindowManagerService陨簇、ActivityManagerService、PackageManagerService等重要的可以binder通信的服務(wù)都運行在這個SystemServer進(jìn)程

Launcher啟動過程

系統(tǒng)啟動的最后一步就是啟動一個應(yīng)用程序來顯示系統(tǒng)中已經(jīng)安裝的應(yīng)用程序河绽,這個程序就叫做Launcher己单。它在啟動過程中會請求PackagerMangerService返回系統(tǒng)中已經(jīng)安裝的應(yīng)用程序信息,并將這些信息封裝成一個快捷圖標(biāo)列表顯示在系統(tǒng)屏幕上耙饰。這樣用戶就可以通過點擊快捷圖標(biāo)來啟動相應(yīng)的應(yīng)用程序了纹笼。

在上面SystemServer進(jìn)程分析過程中,我們知道ActivityManagerService(簡稱:AMS)是負(fù)責(zé)四大組件的啟動苟跪、切換和調(diào)度的廷痘。系統(tǒng)桌面本身也是一個Activity,所以Launcher的啟動是在AMS中進(jìn)行的件已,啟動Launcher的入口是AMSsystemReady方法笋额。該方法是在SystemServerstartOtherServices方法中被調(diào)用的,下面就看一下該方法的實現(xiàn)代碼:

private void startOtherServices(){
    ......
    mActivityManagerService.systemReady(() -> {
        Slog.i(TAG, "Making services ready");
        traceBeginAndSlog("StartActivityManagerReadyPhase");
        mSystemServiceManager.startBootPhase(
                SystemService.PHASE_ACTIVITY_MANAGER_READY);
        traceEnd();
        traceBeginAndSlog("StartObservingNativeCrashes");
        try {
            mActivityManagerService.startObservingNativeCrashes();
        } catch (Throwable e) {
            reportWtf("observing native crashes", e);
        }
        traceEnd();
    ......
}

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

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

該方法中調(diào)用了ActivityStackSupervisorresumeFocusedStackTopActivityLocked()方法篷扩。

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

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    ......
    return false;
}

ActivityStack是用來描述Activity堆棧的兄猩。

最后經(jīng)過重重調(diào)用,最終會調(diào)用AMSstartHomeActivityLocked方法鉴未。

boolean startHomeActivityLocked(int userId, String reason) {
    //判斷系統(tǒng)的運行模式和mTopAction的值
    if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
            && mTopAction == null) {
        return false;
    }
    獲取Luncher啟動所需要的Intent
    Intent intent = getHomeIntent();
    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) {
            intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
            final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
            final String myReason = reason + ":" + userId + ":" + resolvedUserId;
            //啟動Luncher
            mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
        }
    } else {
        Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
    }
    return true;
}

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

mFactoryTest代表系統(tǒng)運行模式枢冤,運行模式有三種:非工廠模式、低級工廠模式和高級工廠模式铜秆;mTopAction表示第一個被啟動Activity組件的Action淹真,它的默認(rèn)值為:Intent.ACTION_MAIN

getHomeIntent方法中连茧,如果mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL(低級工廠模式)趟咆,Category的值為:Intent.CATEGORY_HOME。也就是說如果系統(tǒng)運行模式不是低級工廠模式那么:
action = Intent.ACTION_MAIN
category = Intent.CATEGORY_HOME
而服務(wù)這個描述的應(yīng)用程序就是Luncher梅屉,因為LuncherAndroidManifest文件中的intent-filter匹配了這兩個值:

/packages/apps/Launcher3/AndroidManifest.xml

<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
<uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>
......
<application
    ......
    <activity
        android:name="com.android.launcher3.Launcher"
        android:launchMode="singleTask"
        android:clearTaskOnLaunch="true"
        android:stateNotNeeded="true"
        android:windowSoftInputMode="adjustPan"
        android:screenOrientation="unspecified"
        android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
        android:resizeableActivity="true"
        android:resumeWhilePausing="true"
        android:taskAffinity=""
        android:enabled="true">
        <intent-filter>
            //匹配規(guī)則
            <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"/>
            <category android:name="android.intent.category.LAUNCHER_APP" />
        </intent-filter>
    </activity>
    ......
</application>
</manifest>

Luncher完成啟動后,作為桌面它會顯示應(yīng)用程序圖標(biāo)鳞贷。

參考《Android進(jìn)階解密》

實戰(zhàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坯汤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子搀愧,更是在濱河造成了極大的恐慌惰聂,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咱筛,死亡現(xiàn)場離奇詭異搓幌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)迅箩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門溉愁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饲趋,你說我怎么就攤上這事拐揭〕敷。” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵堂污,是天一觀的道長家肯。 經(jīng)常有香客問我,道長盟猖,這世上最難降的妖魔是什么讨衣? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮式镐,結(jié)果婚禮上反镇,老公的妹妹穿的比我還像新娘。我一直安慰自己碟案,他們只是感情好愿险,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著价说,像睡著了一般辆亏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鳖目,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天扮叨,我揣著相機(jī)與錄音,去河邊找鬼领迈。 笑死彻磁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狸捅。 我是一名探鬼主播衷蜓,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼尘喝!你這毒婦竟也來了磁浇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤朽褪,失蹤者是張志新(化名)和其女友劉穎置吓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缔赠,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡衍锚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嗤堰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戴质。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出置森,到底是詐尸還是另有隱情斗埂,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布凫海,位于F島的核電站呛凶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏行贪。R本人自食惡果不足惜漾稀,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望建瘫。 院中可真熱鬧崭捍,春花似錦、人聲如沸啰脚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橄浓。三九已至粒梦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荸实,已是汗流浹背匀们。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留准给,地道東北人泄朴。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像露氮,于是被迫代替她去往敵國和親祖灰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容