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

主要流程

簡化流程圖

init進程啟動過程

init進程是Android系統(tǒng)中用戶空間的第一個進程。進程號為1。

引入init進程

第一步

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

第二步

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

第三步

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

啟動init進程就會執(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ù)進行初始化
    property_init();
    ......

    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(ERROR) << "epoll_create1 failed";
        exit(1);
    }
    //用于設(shè)置子進程信號處理函數(shù),如果子進程異常退出,init進程會調(diào)用該函 
    //數(shù)中設(shè)置的信號處理函數(shù)進行處理。
    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進程主要做了三件事:

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

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

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

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

  • 解析init.rc文件,創(chuàng)建Zygote進程。

該文件的路徑為:system/core/rootdir/init.rc。它是一個非常重要的配置文件,是由Android初始化語言編寫的腳本。Android8.0對該文件進行來拆分,每個服務(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進程的創(chuàng)建,所以只貼出了init.rc文件中的Serivice類型的語句,省略了其他語句;這是由Android初始化語言編寫的。它的格式如下:
service <name> <pathname> [ <argument> ]* //名字 執(zhí)行程序路徑 傳遞參數(shù)
< option > //修飾詞,影響什么時候啟動,如何啟動service。
< option >
......
上面的代碼的含義就是:通知init進程創(chuàng)建名為zygote的進程,這個進程的執(zhí)行路徑為:/system/bin/app/_process64,其后面的代碼是傳遞給app_process64的參數(shù)。class main指的是zygoteclassnamemain

init.rc中的Service類型的語句有相應(yīng)的類來進行解析,Service語句采用ServiceParser來進行解析,該實現(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)建子進程
        pid = fork();
    }

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

調(diào)用execve 函數(shù),子進程就會被啟動,就是執(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進程

Zygote進程

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

Zygote進程都是通過fock自身來創(chuàng)建子進程的,這樣Zygote進程以及子進程都會進入app_main.cppmain函數(shù),所以在上述代碼中先區(qū)分來當前運行在哪個進程中。運行Zygote進程就會執(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虛擬機
    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語言編寫的,當前的運行邏輯在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());
            //預加載類和資源
            preload(bootTimingsTraceLog);
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            bootTimingsTraceLog.traceEnd(); // ZygotePreload
        } else {
            Zygote.resetNicePriority();
        }
        //啟動SystemServer進程
        if (startSystemServer) {
            startSystemServer(abiList, socketName, zygoteServer);
        }
        //等待AMS請求,里面是一個while(true)循環(huán)
        zygoteServer.runSelectLoop(abiList);
        zygoteServer.closeServerSocket();
    }......
}

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

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

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

SystemServer進程

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

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)建一個子進程,也就是SystemServer進程
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
    //當前代碼運行在子進程中,也就是SystemServer進程
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        //SystemServer進程復制了Zygote進程的地址空間,因此也會得到Zygote創(chuàng)建的Socket。
        //該Socket對SystemServer進程沒有用,所以要關(guān)閉。
        zygoteServer.closeServerSocket();
        //處理SystemServer進程
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

從上面代碼可以看出,SystemServer進程的用戶id和用戶組id被設(shè)置為1000,并且擁有1001~1010、1018、1021、1032、3001~3010的權(quán)限;進程名字為system_server;啟動的類名為:com.android.server.SystemServer

創(chuàng)建出SystemServer進程之后就會在該進程調(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進程就可以使用Binder于其他進程進行通信了。

創(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進程的入口。(在Zygote
啟動SystemServer進程之后,SystemServer進程做了很多準備工作,這些工作都是在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方法

這樣就進入了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");
        //啟動引導服務(wù)
        startBootstrapServices();
        //啟動核心服務(wù)
        startCoreServices();
        //啟動其他服務(wù)
        startOtherServices();
        SystemServerInitThreadPool.shutdown();
    }......
}

通過上面可以看出系統(tǒng)服務(wù)分為三種:
1.引導服務(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ù)表:

引導服務(wù) 作用
Installer 系統(tǒng)安裝APK時的一個服務(wù),啟動完成Installer服務(wù)之后才能啟動其他的服務(wù)
ActivityManagerService 負責四大組件的啟動、切換和調(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進行安、解析、刪除、卸載等操作
...... .....
核心服務(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 藍牙管理服務(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,所以是不可以進行Binder通信的,也就是由它管理的服務(wù)是用于進程內(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ù)是用于進程間通信的:用于系統(tǒng)C/S架構(gòu)中的Binder通信機制。客戶端要使用某個Service,需要先到ServiceManager中查詢Service的信息,然后根據(jù)該信息與Service所在的Server進程建立通信,這樣客戶端就可以使用Service了。

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

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

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

Launcher啟動過程

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

在上面SystemServer進程分析過程中,我們知道ActivityManagerService(簡稱:AMS)是負責四大組件的啟動、切換和調(diào)度的。系統(tǒng)桌面本身也是一個Activity,所以Launcher的啟動是在AMS中進行的,啟動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,它的默認值為: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)用程序圖標。

參考《Android進階解密》

實戰(zhàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

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