> 文档中心 > Android系统启动流程

Android系统启动流程


Android启动流程

本文将结合源码介绍开机到系统完成启动的整个过程,源码基于Android9.0http://androidxref.com,文中若有表述不当或则错误的地方,希望大家帮忙指正,

第一阶段Bootloader

系统加电或复位后,CPU会从一个固定的地址开始执行,比如从从地址0x00000000取第一条指令,则需要将开发板的ROM或则flash映射到这个地址,并且将Bootloader程序存储在相应的Flash位置,这样CPU上电后就会首先执行它,
说的通俗点就是,当按下电源键的时候,引导芯片会执行固化在ROM中的一段代码,将Bootloader加载到RAM中,并开始执行

关于Bootloader

以前就一直有个疑问,到底什么是bootloader,简单地说,bootloader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。所以Bootloader的主要功能是引导操作系统启动,而在嵌入式系统中,并没有一个统一的Bootloader,按照处理器体系结构和功能复杂程度的不同,有一系列可以选用的Bootloader,常用的比如说U-Boot

Bootloader里做了些什么

主要分为两个阶段

  1. 初始化阶段,初始化CPU时钟,内存,串口等
  2. 启动Kernel,这里会检测组合键的输入,当发现有特殊的组合按键,就会进入对应的模式
  • 组合键启动到fastboot模式,命令或则sd卡烧写模式,不加载内核及文件系统,可以通过数据线和电脑连接,在电脑执行一些命令,如刷镜像到手机上。可以理解为实现了一个简单的通信协议,接受命令并更新镜像文件。
  • 组合键启动recovery模式,加载recovery.img,包含内核,部分文件系统,可以读取sdcard目录下的update.zip进行刷机,清除用户数据,可以理解为一个小型的操作系统,和正常启动进入的系统kernel差不多,只是init及之后干的事情不同
  • 开机Power,正常启动系统,加载boot.img,boot.img包含内核,基本文件系统,用于正常启动设备

第二阶段Kernel

因为不是Kernel开发者,所以这部分内容本身就一知半解,只能做个简单的描述,有需要的可以去深入了解,关于Kernel启动可以大致分为三部分

  1. zImage解压缩,也就是自解压的过程
  2. 汇编启动阶段,主要设置ARM处理器的工作模式,创建初始化页表,设置C代码运行环境,跳转到内核第一个真正的C函数startkernel开始执行
  3. C启动阶段,包括Android的初始化的全部工作,然后启动系统第一个进程init

第三阶段Android系统启动

init进程

作为Android系统的第一个进程,最先开始的便是其main方法,源码路径/system/core/init/init.cpp

int main(int argc, char** argv) {    //省略...    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);    //第一阶段    if (is_first_stage) { boot_clock::time_point start_time = boot_clock::now(); // Clear the umask. umask(0); clearenv(); setenv("PATH", _PATH_DEFPATH, 1); //在initramdisk中获得需要的基本文件系统设置 //让rc文件解决剩下的问题 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)); if constexpr (WORLD_WRITABLE_KMSG) {     mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)); } mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)); mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)); //...省略    }    // 初始化的第二阶段    InitKernelLogging(argv);    LOG(INFO) << "init second stage started!";    //设置所有进程都可以访问的会话密钥。它会保存FBE加密密钥之类的东西。任何进程都不应覆盖其会话密钥    keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);    // Indicate that booting is in progress to background fw loaders, etc.    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));    //初始化属性服务    property_init();    // 如果参数同时在命令行和DT中传递,DT中设置的属性总是优先于命令行属性。    process_kernel_dt();    process_kernel_cmdline();    //将内核变量传到内部变量由init使用,以及当前所需的属性    export_kernel_boot_props();    // Make the time that init started available for bootstat to log.    property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));    property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));    // Set libavb version for Framework-only OTA match in Treble build.    const char* avb_version = getenv("INIT_AVB_VERSION");    if (avb_version) property_set("ro.boot.avb_version", avb_version);    // 清空设置的环境变量    unsetenv("INIT_SECOND_STAGE");    unsetenv("INIT_STARTED_AT");    unsetenv("INIT_SELINUX_TOOK");    unsetenv("INIT_AVB_VERSION");    // 设置第二阶段的selinux    SelinuxSetupKernelLogging();    SelabelInitialize();    SelinuxRestoreContext();    // 创建epoll句柄    epoll_fd = epoll_create1(EPOLL_CLOEXEC);    if (epoll_fd == -1) { PLOG(FATAL) << "epoll_create1 failed";    }    //设置子进程处理函数    sigchld_handler_init();    if (!IsRebootCapable()) { // If init does not have the CAP_SYS_BOOT capability, it is running in a container. // In that case, receiving SIGTERM will cause the system to shut down. InstallSigtermHandler();    }    property_load_boot_defaults();    export_oem_lock_status();    //启动属性服务    start_property_service();    set_usb_controller();    const BuiltinFunctionMap function_map;    Action::set_function_map(&function_map);    subcontexts = InitializeSubcontexts();    ActionManager& am = ActionManager::GetInstance();    ServiceList& sm = ServiceList::GetInstance();    //加载解析init.rc    LoadBootScripts(am, sm);    //...省略    return 0;}

从源码可以看到,main函数中大概经历了三个过程

  • 创建并挂载启动所需要的文件系统tmpfs、devpts等
  • 初始化并启动属性服务
  • 加载并解析init.rc文件

继续看下LoadBootScripts的源码

Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {    Parser parser;    parser.AddSectionParser("service", std::make_unique(&service_list, subcontexts));    parser.AddSectionParser("on", std::make_unique(&action_manager, subcontexts));    parser.AddSectionParser("import", std::make_unique(&parser));    return parser;}static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {    Parser parser = CreateParser(action_manager, service_list);    std::string bootscript = GetProperty("ro.boot.init_rc", "");    if (bootscript.empty()) { parser.ParseConfig("/init.rc"); if (!parser.ParseConfig("/system/etc/init")) {     late_import_paths.emplace_back("/system/etc/init"); } if (!parser.ParseConfig("/product/etc/init")) {     late_import_paths.emplace_back("/product/etc/init"); } if (!parser.ParseConfig("/odm/etc/init")) {     late_import_paths.emplace_back("/odm/etc/init"); } if (!parser.ParseConfig("/vendor/etc/init")) {     late_import_paths.emplace_back("/vendor/etc/init"); }    } else { parser.ParseConfig(bootscript);    }}

可以看出,根据不同条件来确认,需要使用那个init.rc文件,然后开始解析对应的rc文件

init.rc启动脚本

init.rc语法介绍

一个完整的rc脚本由四种类型的行为声明而成

  • Action(动作)
    action其实就是在响应某个事件的过程,当描述的事件发生时,将会依次执行事件下面的command,语法如下:
on     #触发条件      #执行命令1      #执行命令2      #执行命令3    ...
  • Commands(命令)
    常见的比如mkdir、chmod、chown、mount等
  • Service(服务)
    service其实就是可执行程序,像后面要执行的zygote就是作为service执行的,在特定选项的约束下,会被执行或重启,格式如下
service               ...

其中name表示服务名,path表示服务所在路径,argument启动参数,option对服务的约束项

  • Option(选项)
    对服务的约束,常用有:
    | Option | Description |
    | :-----| :-----|
    | class | 当服务指定了class名,则同一个class的所有服务必须同时启动或停止,默认情况下,class名为default|
    | user | 在服务启动前,将用户切换到,默认情况下都是root |
    | group … | 启动服务前将用户组切换到 |
    | socket …| 将创建一个名为dev/socket/ 的unix domain socket,然后将fd值返回给启动它的进程 |
    | onrestart | 服务重启时执行某些命令 |

关键服务的启动

init进程通过解析init.rc文件,会陆续启动其它关键的系统服务进程,而其中比较重要的就是ServiceManager,Zygote,SystemServer

ServiceManager进程启动

ServiceManager是Binder机制中非常重要的组成,负责Binder服务在其注册时提供的名称到驱动分配值的解析,看下它在init.rc中的描述

on post-fs    # Load properties from    #     /system/build.prop,    #     /odm/build.prop,    #     /vendor/build.prop and    #     /factory/factory.prop    load_system_props    # start essential services    start logd    //启动servicemanager    start servicemanager    start hwservicemanager    start vndservicemanager

这里对应的是/frameworks/native/cmds/servicemanager/servicemanager.rc

service servicemanager /system/bin/servicemanager    class core animation    user system    group system readproc    critical    onrestart restart healthd    onrestart restart zygote    onrestart restart audioserver    onrestart restart media    onrestart restart surfaceflinger    onrestart restart inputflinger    onrestart restart drm    onrestart restart cameraserver    onrestart restart keystore    onrestart restart gatekeeperd    writepid /dev/cpuset/system-background/tasks    shutdown critical

critical选项说明它是系统的关键进程,表示如果在4分钟内该进程若异常退出超过四次,将重启设备并进入还原模式。当servicemanager每次重启的时候,其它进程zygote,audioserver等也会restart

Zygote进程启动

由于硬件差异,64位和32位机器中Zygote会区别对待,在import时通过ro.zygote属性确认需要加载的zygote.rc脚本
init.rc的源码路径在/system/core/rootdir/init.rc下,部分内容如下

import /init.environ.rcimport /init.usb.rcimport /init.${ro.hardware}.rcimport /vendor/etc/init/hw/init.${ro.hardware}.rcimport /init.usb.configfs.rcimport /init.${ro.zygote}.rcon early-init    # Set init and its forked children's oom_adj.    write /proc/1/oom_score_adj -1000    //省略...

对应的zygote.rc在同级目录下可以找到:

Name
init.rc
init.zygote32.rc
init.zygote32_64.rc
init.zygote64.rc
init.zygote64_32.rc

这里已64位为例,打开对应的文件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 reserved_disk    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启动的其实是一个可执行文件/system/bin/app_process64,启动时会传入启动参数
-Xzygote /system/bin --zygote --start-system-server,同时会创建对应的socket

app_process64进程

上面可执行文件的实现其实是在/frameworks/base/cmds/app_process/app_main.cpp中,查看同级目录下的Android.mk就可以看出来。接下来看下它的main方法

int main(int argc, char* const argv[]){    //...    // Parse runtime arguments.  Stop at first unrecognized option.    bool zygote = false;    bool startSystemServer = false;    bool application = false;    String8 niceName;    String8 className;    ++i;  // Skip unused "parent dir" argument.    while (i < argc) { const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) {     zygote = true;     niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) {     startSystemServer = true; } else if (strcmp(arg, "--application") == 0) {     application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) {     niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) {     className.setTo(arg);     break; } else {     --i;     break; }    }    //...    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.");    }}

这个代码还是很容易看懂的,首先是解析传入的启动参数,根据--zygote参数,来确认执行那个方法,这里有两种情况

  • 执行ZygoteInit,也就是去初始化zygote进程
  • 执行RuntimeInit,这里其实就是启动普通应用程序

我们现在是初次启动,会走入第一个分支,也就是去执行ZygoteInit,可以看到,这里是通过runtime变量去调用start方法,实际上调用的是其父类AndroidRuntime的start方法

AndroidRuntime

对应的源码位置是/frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector& options, bool zygote){    ALOGD(">>>>>> START %s uid %d <<<<<<\n",     className != NULL ? className : "(unknown)", getuid());    static const String8 startSystemServer("start-system-server");    //判断是否是启动systemServer    for (size_t i = 0; i < options.size(); ++i) { if (options[i] == startSystemServer) {    /* track our progress through the boot sequence */    const int LOG_BOOT_PROGRESS_START = 3000;    LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); }    }    //从环境变量ANDROID_ROOT中读取系统目录    const char* rootDir = getenv("ANDROID_ROOT");    if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) {     LOG_FATAL("No root directory specified, and /android does not exist.");     return; } setenv("ANDROID_ROOT", rootDir, 1);    }    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);    /* start the virtual machine */    JniInvocation jni_invocation;    //初始化jni接口    jni_invocation.Init(NULL);    JNIEnv* env;    //启动虚拟机    if (startVm(&mJavaVM, &env, zygote) != 0) { return;    }    //这里实际上调用的子类的重写方法,也就是前面app_main.cpp中的AppRuntime    onVmCreated(env);    //...省略以下代码,主要去调用上面的java方法Zygoteinit}

整体来看,经历了以下几个步骤

  • 判断是否启动SystemSever
  • 从环境变量ANDROID_ROOT中读取系统目录
  • 初始化jni接口,并启动虚拟机
  • 启动Zygoteinit类的main()函数
Zygoteinit

看一下他的主函数都做了什么操作,源码路径/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); // Mark zygote start. This ensures that thread creation will throw // an error. ZygoteHooks.startZygoteNoThreadCreation(); // Zygote goes into its own process group. try {     Os.setpgid(0, 0); } catch (ErrnoException ex) {     throw new RuntimeException("Failed to setpgid(0,0)", ex); } final Runnable caller; try {     // Report Zygote start time to tron unless it is a runtime restart     //...     for (int i = 1; i < argv.length; i++) {  if ("start-system-server".equals(argv[i])) {      startSystemServer = true;  } else if ("--enable-lazy-preload".equals(argv[i])) {      enableLazyPreload = true;  } else if (argv[i].startsWith(ABI_LIST_ARG)) {      abiList = argv[i].substring(ABI_LIST_ARG.length());  } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {      socketName = argv[i].substring(SOCKET_NAME_ARG.length());  } else {      throw new RuntimeException("Unknown command line argument: " + argv[i]);  }     }     if (abiList == null) {  throw new RuntimeException("No ABI list supplied.");     }     //注册一个Socket     zygoteServer.registerServerSocketFromEnv(socketName);     // In some configurations, we avoid preloading resources and classes eagerly.     // In such cases, we will preload things prior to our first fork.     //判断是否需要预加载     if (!enableLazyPreload) {  bootTimingsTraceLog.traceBegin("ZygotePreload");  EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,      SystemClock.uptimeMillis());  //预加载各种资源类  preload(bootTimingsTraceLog);  EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,      SystemClock.uptimeMillis());  bootTimingsTraceLog.traceEnd(); // ZygotePreload     } else {  Zygote.resetNicePriority();     }     //...     if (startSystemServer) {  //启动SystemServer  Runnable r = forkSystemServer(abiList, socketName, zygoteServer);  // {@code r == null} in the parent (zygote) process, and {@code r != null} in the  // child (system_server) process.  if (r != null) {      r.run();      return;  }     }     caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) {     Log.e(TAG, "System zygote died with exception", ex);     throw ex; } finally {     zygoteServer.closeServerSocket(); } ...    }

从上面看出,Zygote的主函数其实不复杂,主要完成了以下工作

  • 注册一个Socket
    当有新程序需要时,系统会通过这个socket在第一时间通知ZygoteServer
  • 预加载各类资源
    通过preload函数,加载虚拟机运行时需要的各类资源
    beginIcuCachePinning();    preloadClasses();    preloadResources();    nativePreloadAppProcessHALs();    preloadOpenGL();    preloadSharedLibraries();    preloadTextResources();    WebViewFactory.prepareWebViewInZygote();
  • 启动SystemServer
    当启动zygote时,启动参数里面带有--start-system-server时,便会调用forkSystemServer来创建SystemServer,看下这个函数的实现:
    private static Runnable forkSystemServer(String abiList, String socketName,     ZygoteServer zygoteServer) { //... String args[] = {     "--setuid=1000",     "--setgid=1000",     "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",     "--capabilities=" + capabilities + "," + capabilities,     "--nice-name=system_server",     "--runtime-args",     "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,     "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try {     parsedArgs = new ZygoteConnection.Arguments(args);     ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);     ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);     boolean profileSystemServer = SystemProperties.getBoolean(      "dalvik.vm.profilesystemserver", false);     if (profileSystemServer) {  parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;     }     //通过这个函数去fork一个新的进程     pid = Zygote.forkSystemServer(      parsedArgs.uid, parsedArgs.gid,      parsedArgs.gids,      parsedArgs.runtimeFlags,      null,      parsedArgs.permittedCapabilities,      parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) {     throw new RuntimeException(ex); } /* For child process */ if (pid == 0) {     if (hasSecondZygote(abiList)) {  waitForSecondaryZygote(socketName);     }     zygoteServer.closeServerSocket();     return handleSystemServerProcess(parsedArgs); } return null;    }

上述代码通过调用Zygote.forkSystemServer去创建了一个新进程(具体的fork流程后续再出文章分析),并返回pid,而当pid=0时,将去执行handleSystemServerProcess,继续看这个函数的实现

    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) { // set umask to 0077 so new files and directories will default to owner-only permissions. //... final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH"); if (systemServerClasspath != null) {     //... } else {     ClassLoader cl = null;     if (systemServerClasspath != null) {  cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);  Thread.currentThread().setContextClassLoader(cl);     }     /*      * Pass the remaining arguments to SystemServer.      */     return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } /* should never reach here */    }

这里实际上是去调用ZygoteInit.zygoteInit

    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { if (RuntimeInit.DEBUG) {     Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); } Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); RuntimeInit.redirectLogStreams(); //初始化通用部分 RuntimeInit.commonInit(); //初始化native函数 ZygoteInit.nativeZygoteInit(); //初始化Application return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);    }

在这里有三个初始化函数:

  • commonInit初始化通用部分
  • nativeZygoteInit初始化native部分的服务,内部去调用startThreadPool开启了Binder线程池,保证其他进程能正确访问到zygote
  • applicationInit初始化java服务部分,函数内部根据前面传入的参数,找到SystemServer的main方法,并调用

通过上述步骤,Zygote成功打开了虚拟机,并fock出新进程pid=0,最后去调用SystemServer的main方法

SystemServer启动

这里的main方法,只是一个入口,里面通过new SystemServer().run()去调用了run方法,下面看一下该方法的实现

    private void run() { try {     //...省略,一些初始化设置,包括记录VM信息,设置线程优先级,堆使用率等     // 准备主线程的looper     android.os.Process.setThreadPriority(  android.os.Process.THREAD_PRIORITY_FOREGROUND);     android.os.Process.setCanSelfBackground(false);     Looper.prepareMainLooper();     Looper.getMainLooper().setSlowLogThresholdMs(      SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);     // 加载本地服务库android_servers.so     System.loadLibrary("android_servers");     // Check whether we failed to shut down last time we tried.     // This call may not return.     performPendingShutdown();     // 创建SystemContext     createSystemContext();     // 创建SystemServiceManager     mSystemServiceManager = new SystemServiceManager(mSystemContext);     mSystemServiceManager.setStartInfo(mRuntimeRestart,      mRuntimeStartElapsedTime, mRuntimeStartUptime);     LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);     // 为可以并行的InitThread准备线程池     SystemServerInitThreadPool.get(); } finally {     traceEnd();  // InitBeforeStartServices } // Start services. try {     //打开一些列的其它服务     traceBeginAndSlog("StartServices");     //打开系统的核心服务     startBootstrapServices();     //启动优先级略低的服务     startCoreServices();     //这里面的服务优先级最低,但是很多     startOtherServices();     SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) {     throw ex; } finally {     traceEnd(); } StrictMode.initVmDefaults(null); if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {     int uptimeMillis = (int) SystemClock.elapsedRealtime();     MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);     final int MAX_UPTIME_MILLIS = 60 * 1000;     if (uptimeMillis > MAX_UPTIME_MILLIS) {  Slog.wtf(SYSTEM_SERVER_TIMING_TAG,   "SystemServer init took too long. uptimeMillis=" + uptimeMillis);     } } // 开启loop循环,直到系统关机 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");    }

看完代码来总结一下,SystemServer的主要工作:

  • 初始化设置
  • 准备MainLooper
  • 创建SystemServiceManager,通过它来统一管理
  • 顺序启动系统的剩余服务,核心的PMS,AMS,WMS等所有需要启动的系统服务

最后调用Looper.loop()进入循环中,并且依托zygoteInit中启动的Binder服务接受外部的请求。随着一些列服务的启动Android系统就算是正式启动了,但是我们最终需要的是看到Launcher界面,而不是一堆系统服务所以,解析来继续看Launcher的启动

Launcher的启动

在前面SystemServer启动完一系列系统服务之后,便会调用AMS的systemReady方法通知AMS可以启动第三方的代码了

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {    // 省略服务启动代码...    mActivityManagerService.systemReady(() -> {    Slog.i(TAG, "Making services ready");    t.traceBegin("StartActivityManagerReadyPhase");    mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);    //...    })}

接下来看AMS的systemReady方法

    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { //... synchronized (this) {     //只启动支持加密的持久应用程序;一旦用户解锁我们会回来并启动无意识应用程序     startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);     // 启动初始Activity     mBooting = true;     //为系统用户启用home活动,以便系统始终可以启动     //当系统用户未安装时,我们不会这样做,因为在这种情况下,安装向导应该是处理家庭活动的向导     if (UserManager.isSplitSystemUser() &&      Settings.Secure.getInt(mContext.getContentResolver(),    Settings.Secure.USER_SETUP_COMPLETE, 0) != 0) {  ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);  try {      AppGlobals.getPackageManager().setComponentEnabledSetting(cName,PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,UserHandle.USER_SYSTEM);  } catch (RemoteException e) {      throw e.rethrowAsRuntimeException();  }     }     startHomeActivityLocked(currentUserId, "systemReady");     //...

这里是通过调用startHomeActivityLocked启动Launcher,看下方法实现

    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;    }    boolean startHomeActivityLocked(int userId, String reason) { //...省略 Intent intent = getHomeIntent(); // ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null) {     intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));     // Don't do this if the home app is currently being     // instrumented.     aInfo = new ActivityInfo(aInfo);     aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);     ProcessRecord app = getProcessRecordLocked(aInfo.processName,      aInfo.applicationInfo.uid, true);     if (app == null || app.instr == null) {  intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);  final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);  // For ANR debugging to verify if the user activity is the one that actually  // launched.  final String myReason = reason + ":" + userId + ":" + resolvedUserId;  mActivityStartController.startHomeActivity(intent, aInfo, myReason);     } } else {     Slog.wtf(TAG, "No home screen found for " + intent, new Throwable()); } return true;    }

这里分大概分三个步骤:

  • 首先通过getHomeIntent创建了一个CATEGORY_HOME类型的Intent
  • 通过resolveActivityInfo向PMS查询Category类型为HOME的Activity
  • 通过startHomeActivity去打开Activity

到这里Launcher启动流程就结束了,至于Activity的详细启动流程我之前的文章已经分析过了,这里就不重复去看了,有兴趣的可以去看一下。接下来再去看一下,开机广播的发送地方

开机广播的发送

当Activity启动成功后,会调用AMS的activityIdle通知AMS:

    @Override    public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { final long origId = Binder.clearCallingIdentity(); synchronized (this) {     ActivityStack stack = ActivityRecord.getStackLocked(token);     if (stack != null) {  ActivityRecord r =   mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,    false /* processPausingActivities */, config);  if (stopProfiling) {      if ((mProfileProc == r.app) && mProfilerInfo != null) {   clearProfilerLocked();      }  }     } } Binder.restoreCallingIdentity(origId);    }

这里实际调用的mStackSupervisor.activityIdleInternalLocked方法

    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,     boolean processPausingActivities, Configuration config) { if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token); ArrayList finishes = null; ArrayList startingUsers = null; int NS = 0; int NF = 0; boolean booting = false; boolean activityRemoved = false; ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r != null) {     //...     if (isFocusedStack(r.getStack()) || fromTimeout) {  booting = checkFinishBootingLocked();     } } //... return r;    }

因为刚开机,所以会去调用checkFinishBootingLocked方法

    private boolean checkFinishBootingLocked() { //mService.mBooting是AMS在AMS.systemRead()中,调用startHomeActivityLocked()之前设置为ture的 final boolean booting = mService.mBooting; boolean enableScreen = false; mService.mBooting = false; //这时候因为没有系统还未启动完毕,因此该值为false if (!mService.mBooted) {     mService.mBooted = true;     enableScreen = true; } if (booting || enableScreen) {     mService.postFinishBooting(booting, enableScreen); } return booting;    }    void postFinishBooting(boolean finishBooting, boolean enableScreen) { mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,  finishBooting ? 1 : 0, enableScreen ? 1 : 0));    }

这里发送了一个FINISH_BOOTING_MSG的消息,找到对应的handleMessage方法:

 public void handleMessage(Message msg) {     case FINISH_BOOTING_MSG: {  if (msg.arg1 != 0) {      Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");      finishBooting();      Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  }  if (msg.arg2 != 0) {      enableScreenAfterBoot();  }  break;     }    };

从上面方法可以知道,msg.arg1和msg.arg2都不为0,所以会先执行finishBooting再执行enableScreenAfterBoot,先看下finishBooting:

    final void finishBooting() { synchronized (this) {     if (!mBootAnimationComplete) {  mCallFinishBooting = true;  return;     }     mCallFinishBooting = false; } //... synchronized (this) {     //...     SystemProperties.set("sys.boot_completed", "1");     // And trigger dev.bootcomplete if we are not showing encryption progress     if (!"trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt"))      || "".equals(SystemProperties.get("vold.encrypt_progress"))) {  SystemProperties.set("dev.bootcomplete", "1");     }     mUserController.sendBootCompleted(      new IIntentReceiver.Stub() {   @Override   public void performReceive(Intent intent, int resultCode,    String data, Bundle extras, boolean ordered,    boolean sticky, int sendingUser) {synchronized (ActivityManagerService.this) {    requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);}   }      });     mUserController.scheduleStartProfiles(); }    }    @Override    public void bootAnimationComplete() { final boolean callFinishBooting; synchronized (this) {     callFinishBooting = mCallFinishBooting;     mBootAnimationComplete = true; } if (callFinishBooting) {     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");     finishBooting();     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); }    }

通过mBootAnimationComplete来判断开机动画是否结束播放,当为false时,则会直接返回并设置mCallFinishBooting为true,此时待开机动画播放结束后,执行到函数bootAnimationComplete时,将mBootAnimationComplete设置为true,并且再次调用finishBooting方法

当一切都就绪后,会调用mUserController.sendBootCompleted,内部经过一些列调用最终到finishUserUnlockedCompleted,并在此发送开机广播ACTION_BOOT_COMPLETED。

    private void finishUserUnlockedCompleted(UserState uss) { //...省略 final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT  | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mInjector.broadcastIntent(bootIntent, null, new IIntentReceiver.Stub() {      @Override      public void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, int sendingUser)throws RemoteException {   Slog.i(UserController.TAG, "Finished processing BOOT_COMPLETED for u" + userId);      }  }, 0, null, null,  new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},  AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);    }

你以为到这儿就完了吗?别忘了上面还有个函数enableScreenAfterBoot,看下它都做了啥:

    void enableScreenAfterBoot() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,  SystemClock.uptimeMillis()); mWindowManager.enableScreenAfterBoot(); synchronized (this) {     updateEventDispatchingLocked(); }    }

进入WindowManager.enableScreenAfterBoot方法查看

    public void enableScreenAfterBoot() { synchronized(mWindowMap) {     if (DEBUG_BOOT) {  RuntimeException here = new RuntimeException("here");  here.fillInStackTrace();  Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled   + " mForceDisplayEnabled=" + mForceDisplayEnabled   + " mShowingBootMessages=" + mShowingBootMessages   + " mSystemBooted=" + mSystemBooted, here);     }     //保证该函数只调用一次     if (mSystemBooted) {  return;     }     mSystemBooted = true;     hideBootMessagesLocked();     // If the screen still doesn't come up after 30 seconds, give     // up and turn it on.     mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000); } mPolicy.systemBooted(); performEnableScreen();    }

可以看到这里将会发送一个延时30s的消息,最后也会执行performEnableScreen方法,看一下这个方法的实现

    private void performEnableScreen() {     //...     if (!mBootAnimationStopped) {  Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);  // stop boot animation  // formerly we would just kill the process, but we now ask it to exit so it  // can choose where to stop the animation.  SystemProperties.set("service.bootanim.exit", "1");  mBootAnimationStopped = true;     }     //检查开机广播是否播放完成     if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {  if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");  return;     }     try {  //调用SurfaceFlinger的bootFinished()方法  IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");  if (surfaceFlinger != null) {      Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");      Parcel data = Parcel.obtain();      data.writeInterfaceToken("android.ui.ISurfaceComposer");      surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHEDdata, null, 0);      data.recycle();  }     } catch (RemoteException ex) {  Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");     }     EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());     Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);     mDisplayEnabled = true;     if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");     // Enable input dispatch.     mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); } try {     mActivityManager.bootAnimationComplete(); } catch (RemoteException e) { } mPolicy.enableScreenAfterBoot(); // Make sure the last requested orientation has been applied. updateRotationUnchecked(false, false);    }

这里先检测开机动画是否播放完成,若未完成则将通过Binder调用SurfaceFlinger的bootFinished方法,并且设置属性service.bootanim.exit值为1,同时bootanimation在播放开机动画的时候,会去检测该值是否为1。如果值为1并且动画播放完成,则会退出开机动画,此时如果bootanimation没有退出,则又会继续循环调用。最终当bootanimation播放完成后,则去调用mActivityManager.bootAnimationComplete()。然后就回到我们上面分析的过程了

看着有点弯弯绕绕,总结一下其实就是一个检测开机动画播放完成的过程,我们需要等到开机动画结束播放后再去发送开机广播,并且如果30s之后开机动画未完成播放则会强制停止播放,并发送开机广播

总结

到这儿Android的整个开机过程也就算结束了,最后再整体梳理一下整个过程,加深印象:

  • 加载并启动bootloader
  • 启动kernel
  • init进程通过解析init.rc文件,启动Zygote进程
  • Zygote经过一系列调用,启动虚拟机,fork系统进程,等最后启动SysyemServer
  • SystemServer启动后续系统服务,比如AMS,PMS,WMS等
  • 服务启动完成后通知AMS,AMS开始启动launcher,发送开机广播
  • AMS启动Launcher,并且在开机动画结束之后,发送开机广播
  • 启动完成,显示Launcher