IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 源码详解Android 9.0(P) 系统启动流程之SystemServer -> 正文阅读

[移动开发]源码详解Android 9.0(P) 系统启动流程之SystemServer

源码详解Android 9.0(P) 系统启动流程目录:

源码详解Android 9.0(P)系统启动流程之init进程(第一阶段)
源码详解Android 9.0(P)系统启动流程之init进程(第二阶段)
源码详解Android 9.0(P)系统启动流程之init.rc语法规则
源码详解Android 9.0(P)系统启动流程之init进程(第三阶段)
源码详解Android 9.0(P)系统启动流程之核心服务和关键进程启动
源码详解Android 9.0(P)系统启动流程之Zygote进程
源码详解Android 9.0(P)系统启动流程之SystemServer


0. 前言

??在前面的篇章源码详解Android 9.0§ 系统启动流程之Zygote进程中我们重点分析了zygote启动的流程,但是剩余了两个重点的知识点没有讲解,其中之一就是Android system_server进程启动的完整流程,在本篇中我们将要揭开system_server的神秘面纱分析分析它究竟是怎么启动的。


??SystemServer进程是zygote进程启动后,主动“分裂”的第一个进程。如果说zygote孵化了整个Android的Java世界,那么system_server进程就是它的左膀右臂一起掌管Android的Java世界。它负责启动大量的Android系统核心服务,其重要性不言而喻。一旦该进程崩溃,整个Android系统将重新启动。??
??SystemServer对Android意味着什么?这个答案是不言而喻的,它是Android Java世界的精神支柱,虽然Android的Java世界可以说由zygote孵化而来的,但是在我看来zygote也是一个甩手掌柜。而system_server进程则是Android Java世界的核心管理者,为了Java世界的繁华提供着各种服务,事必亲力亲为。
??正是由于zygote和system_server的关系如此密切,所以这两者之间任何一个发生异常,都会导致Android Java的崩溃(所有由Zygote孵化的Java进程都会被销毁,而SystemServer就是由Zygote孵化而来)。若Android Java真的崩溃了,那么Linux系统中的进程init会重新启动“两大支柱”以重建Android Java,也有可能陷入无限死循环启动不了这个就要根据实际情况来看了。

??由此我们也能看出SystemServer地位之高,因此对它的来源、作用和流程我们都需要有一定的了解,废话不多说,代码见~
其中涉及的源码路径如下:

frameworks//base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
frameworks/base/core/java/com/android/internal/os/Zygote.java
frameworks/base/core/jni/AndroidRuntime.cpp
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/app/LoadedApk.java
frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

1. system_server启动的整体概述

??老规矩,在正式开始源码前,先奉上system_server进程启动的整体流程图,这样有助于童靴们心里构建一个整体的流程图谱,这样就可以根据图谱再结合源码达到一一击破,逐个分析的功效。
在这里插入图片描述

2. system_server进程启动

??在前面的篇章源码详解Android 9.0§ 系统启动流程之Zygote进程中我们知道当zygote进程进入到java世界后,在ZygoteInit.java中,将调用startSystemServer函数启动SystemServer进程,其关键代码是:

	public static void main(String argv[]) {
		......
			if (startSystemServer) {
                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;
                }
            }
		......
	}

这段代码中我们重点关注forkSystemServer,从它开始下手。

2.1 forkSystemServer

该代码定义于frameworks//base/core/java/com/android/internal/os/ZygoteInit.java

    /**
     * Prepare the arguments and forks for the system server process.
     *
     * Returns an {@code Runnable} that provides an entrypoint into system_server code in the
     * child process, and {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ......
        /* Hardcoded command line to start the system server */
        //参数准备,system_server进程启动的相关参数
        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;
            }

            /* Request to fork the system server process */
            //重点来了,通过forkSystemServer来fork子进程,进程是system_server
            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)) {//如果有SecondZygote进程需要启动,等待启动完成
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();//关闭zygote原有socket
            return handleSystemServerProcess(parsedArgs);//处理system_server进程相关的事务
        }

        return null;
    }

??从上述源码我们可以看出,该代码的逻辑划分如下:

  • 准备要启动system_server相关的参数并fork新的进程,从上面可以看出system server进程参数信息为uid=1000,gid=1000,进程名为sytem_server
  • 如果对于有两个zygote进程情况,需等待第2个zygote创建完成,这种情况通常发生在加载zygote启动的rc文件为init.zygote32_64.rc或者init.zygote64_32.rc这两种情况下
  • 从zygote进程fork新进程后,关闭zygote原有的socket
  • 调用handleSystemServerProcess,返回一个Runable对象

2.2 Zygote.forkSystemServer

??该代码定义于frameworks/base/core/java/com/android/internal/os/Zygote.java

    /**
     * Special method to start the system server process. In addition to the
     * common actions performed in forkAndSpecialize, the pid of the child
     * process is recorded such that the death of the child process will cause
     * zygote to exit.
     *
     * @param uid the UNIX uid that the new process should setuid() to after
     * fork()ing and and before spawning any threads.
     * @param gid the UNIX gid that the new process should setgid() to after
     * fork()ing and and before spawning any threads.
     * @param gids null-ok; a list of UNIX gids that the new process should
     * setgroups() to after fork and before spawning any threads.
     * @param runtimeFlags bit flags that enable ART features.
     * @param rlimits null-ok an array of rlimit tuples, with the second
     * dimension having a length of 3 and representing
     * (resource, rlim_cur, rlim_max). These are set via the posix
     * setrlimit(2) call.
     * @param permittedCapabilities argument for setcap()
     * @param effectiveCapabilities argument for setcap()
     *
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();//这个分支先不予分析
        // Resets nice priority for zygote process.
        resetNicePriority();
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true, runtimeFlags);
        }
        VM_HOOKS.postForkCommon();//这个也先不予分析
        return pid;
    }

??通过前面我们对zygote启动的流程分析我们可知Android系统的JNI函数绝大分布都是在androidRuntime.cpp中进行注册的,nativeForkSystemServer()本地方法也不例外。这里nativeForkSystemServer会调用com_android_internal_os_Zygote.cpp中的register_com_android_internal_os_Zygote()方法建立native方法的映射关系,所以接下来进入如下方法。

这里有一个小窍门,怎么找到Android系统中Java的本地方法对应的Jni所在文件呢,一般的规则如下:

  1. 将Java类所在的包名中的.转换成_,譬如我们这里的Zygote所在包名为com.android.internal.os,转换后即为com_android_internal_os
  2. 将上述转换后的字符串+"_"+Java类名.cpp,就是我们要找的Jni文件了,譬如我们这里的com_android_internal_os_Zygote.cpp

2.3 nativeForkSystemServer

??通过前面章节我们知道nativeForkSystemServer是一个本地方法,最终通过Jni调用到了com_android_internal_os_Zygote.cpp中的com_android_internal_os_Zygote_nativeForkSystemServer中,代码逻辑如下所示:

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {


  syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, getpid(), 1 | (0 << IOPRIO_CLASS_SHIFT));
  //划重点,fork子进程
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      runtime_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, false, NULL, NULL);
  if (pid > 0) {
      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      //pid大于0,在父进程中即在zygote进程中
      //将子进程SystemServer的pid存在zygote进程的全局变量中
      gSystemServerPid = pid;
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven't published its pid yet. So
      // we recheck here just to make sure that all is well.
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
      	  //如果system_server创建即夭折了,那么就重启zygote进程只得重新开始孵化了
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      }

      // Assign system_server to the correct memory cgroup.
      // Not all devices mount /dev/memcg so check for the file first
      // to avoid unnecessarily printing errors and denials in the logs.
      if (!access("/dev/memcg/system/tasks", F_OK) &&
                !WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) {
        ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);
      }
  }
  return pid;
}

??通过上面的代码可以看到,当system_server创建如果夭折了的话,那么Android将不得不重启zygote进程了。但是需要注意的是,对于Android 5.0以上系统,有两个zygote进程,分别是zygote、zygote64两个进程,system_server的父进程,一般来说64位系统其父进程是zygote64进程(这个是参考gityuan的,不保证正确)。

  • 当kill system_server进程后,只重启zygote64和system_server,不重启zygote;
  • 当kill zygote64进程后,只重启zygote64和system_server,也不重启zygote;
  • 当kill zygote进程,则重启zygote、zygote64以及system_server。

这里提供一个小方法教大伙看系统中那些进程是由zygote64启动的那些是由zygote启动的,具体的步骤如下:

  • 通过ps | grep zygote命令查看当前Android终端运行了几个zygote进程

  • 根据进程号PID看看上面zygote进程的执行文件

    cd /proc/PID(这里的PID为上面进程获取的)
    ls -ali | grep exe
    
  • 我们只要看那些进程的PPID为上述的PID值就可以看出进程分别是由谁孵化的了

    ps | grep PID(这里的PID为上面进程获取的)
    

2.4 ForkAndSpecializeCommon

??该代码依然还是定义在com_android_internal_os_Zygote.cpp中,冗余细节有点多,我们这里只抓主要的,细节的先行放过。

// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint runtime_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jintArray fdsToIgnore, bool is_child_zygote,
                                     jstring instructionSet, jstring dataDir) {
  SetSignalHandlers();//注册信号监听器
  ......
  pid_t pid = fork();//这个是重点,system_server进程是在这里fork出来的

  if (pid == 0) {//这里是system_server进程
    PreApplicationInit();

    // Clean up any descriptors which must be closed immediately
    if (!DetachDescriptors(env, fdsToClose, &error_msg)) {//关闭并清除文件描述符
      fail_fn(error_msg);
    }
    
	......
	
    // If this zygote isn't root, it won't be able to create a process group,
    // since the directory is owned by root.
    if (!is_system_server && getuid() == 0) {//对于非system_server子进程,则创建进程组
        int rc = createProcessGroup(uid, getpid());
        if (rc != 0) {
            if (rc == -EROFS) {
                ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
            } else {
                ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
            }
        }
    }

    std::string error_msg;
    if (!SetGids(env, javaGids, &error_msg)) {//设置group,这个是在zygoteInit中传递过来的
      fail_fn(error_msg);
    }

    if (!SetRLimits(env, javaRlimits, &error_msg)) {//设置资源limits
      fail_fn(error_msg);
    }

    ......

    if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities,
                         &error_msg)) {
      fail_fn(error_msg);
    }

    if (!SetSchedulerPolicy(&error_msg)) {//设置调度策略
      fail_fn(error_msg);
    }

    .....
    //selinxu安全上下文检查
    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
    if (rc == -1) {
      fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
            is_system_server, se_info_c_str, se_name_c_str));
    }

    // Make it easier to debug audit logs by setting the main thread's name to the
    // nice name rather than "app_process".
    if (se_name_c_str == NULL && is_system_server) {
      se_name_c_str = "system_server";
    }
    if (se_name_c_str != NULL) {
      SetThreadName(se_name_c_str);//设置线程名为system_server
    }

    delete se_info;
    delete se_name;

    // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
    UnsetChldSignalHandler();//取消信号监听器
	
	//这里调用的是zygote.callPostForkChildHooks()
    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                              is_system_server, is_child_zygote, instructionSet);
    if (env->ExceptionCheck()) {
      fail_fn("Error calling post fork hooks.");
    }
  } else if (pid > 0) {//zygote进程
    // the parent process

    // We blocked SIGCHLD prior to a fork, we unblock it here.
    if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
      fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
    }
  }
  return pid;
}

??这里可以看到ForkAndSpecializeCommon函数最终调用的是fork()函数创建新的进程,而fork创建进程采用的是COW(写时拷贝技术)这是linux创建进程的标准方法,会有两次return,对于pid==0为子进程的返回,对于pid>0为父进程的返回。

??在文章的开篇我们说到,zygote进程和system_server几乎是同生共死,休戚相关的,那是怎么做到的呢?这里我们看到在zygote进程fork之前,调用SetSigChldHandler函数注册了一个子进程信号监听器。由于子进程共享父进程中的堆及栈信息,因此在子进程中也会有相应的信号处理器。为了避免该信号监听器对子进程的影响,可以看到在子进程中进行了UnsetSigChldHandler的操作。zygote进程和system_server同生共死的密码就在SetSigChldHandler中了。

2.4.1 SetSignalHandlers

??该代码依然还是定义在com_android_internal_os_Zygote.cpp中,我们看看它究竟做了些什么什么操作!

static void SetSignalHandlers() {
  struct sigaction sig_chld = {};
  sig_chld.sa_handler = SigChldHandler;

  if (sigaction(SIGCHLD, &sig_chld, NULL) < 0) {
    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
  }

  struct sigaction sig_hup = {};
  sig_hup.sa_handler = SIG_IGN;
  // 该信号监听器关注子进程结束,对应的处理函数为SigChldHandler
  if (sigaction(SIGHUP, &sig_hup, NULL) < 0) {
    ALOGW("Error setting SIGHUP handler: %s", strerror(errno));
  }
}

这个代码并不神秘,在前面讲解init进程源码分析中也分析过类似的。在这里注册一个信号处理器,来监听子进程的死亡。当子进程死亡后,利用SigChldHandler进行操作。需要注意的是,zygote的信号监听器,关注的是zygote所有的子进程,而不只是SystemServer进程(每次创建一个新的进程时,zygote都会注册对应的监听器)。

2.4.2 SigChldHandler

让我们继续分析SigChldHandler看看它做了些什么工作

// This signal handler is for zygote mode, since the zygote must reap its children
static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;

  // It's necessary to save and restore the errno during this function.
  // Since errno is stored per thread, changing it here modifies the errno
  // on the thread on which this signal handler executes. If a signal occurs
  // between a call and an errno check, it's possible to get the errno set
  // here.
  // See b/23572286 for extra information.
  int saved_errno = errno;

  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
     // Log process-death status that we care about.  In general it is
     // not safe to call LOG(...) from a signal handler because of
     // possible reentrancy.  However, we know a priori that the
     // current implementation of LOG() is safe to call from a SIGCHLD
     // handler in the zygote process.  If the LOG() implementation
     // changes its locking strategy or its use of syscalls within the
     // lazy-init critical section, its use here may become unsafe.
     // 通过status判断子进程结束的原因,并打印相应的log
    if (WIFEXITED(status)) {
      ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
      ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
      if (WCOREDUMP(status)) {
        ALOGI("Process %d dumped core.", pid);
      }
    }

    // If the just-crashed process is the system_server, bring down zygote
    // so that it is restarted by init and system server will be restarted
    // from there.
    if (pid == gSystemServerPid) {//而对于system_sever进程就特别处理了,看来是偏心长子啊
      ALOGE("Exit zygote because system server (%d) has terminated", pid);
      kill(getpid(), SIGKILL);
    }
  }

  // Note that we shouldn't consider ECHILD an error because
  // the secondary zygote might have no children left to wait for.
  if (pid < 0 && errno != ECHILD) {
    ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
  }

  errno = saved_errno;
}

看到这里大伙应该明白了,所有zygote的子进程中,zygote只关心了SystemServer的死活。当其它子进程crash时,zygote只打印了log信息(有点天要下雨娘要嫁人随他去的感觉)。看来我们的zygote是有点偏心长子啊。

2.4.3 UnsetChldSignalHandler

??对于system_server进程恢复默认信号处理,代码位于frameworks\base\core\jni\com_android_internal_os_Zygote.cpp

// Sets the SIGCHLD handler back to default behavior in zygote children.
static void UnsetChldSignalHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SIG_DFL;

  if (sigaction(SIGCHLD, &sa, NULL) < 0) {
    ALOGW("Error unsetting SIGCHLD handler: %s", strerror(errno));
  }
}

??到此system_server进程已完成了创建的所有工作,接下来开始了system_server进程的真正工作。在前面startSystemServer()方法中,zygote进程执行完forkSystemServer()后,新创建出来的system_server进程便进入handleSystemServerProcess()方法。

2.5 handleSystemServerProcess

??兜兜转转又回到了ZygoteInit.java中的handleSystemServerProcess方法中

  //此段代码为2.1 forkSystemServer中部分代码
  if (pid == 0) {
      if (hasSecondZygote(abiList)) {
          waitForSecondaryZygote(socketName);
      }

      zygoteServer.closeServerSocket(); // 关闭从zygote进程那里继承下来server socket
      return handleSystemServerProcess(parsedArgs);
  }

	//代码定义于frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);//我们通过ps查看到的system_server进程名就是在这里设置的
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        //加载SystemServer对应的文件并进行优化
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);//这个会在2.6章节中介绍
            // Capturing profiles is only supported for debug or eng builds since selinux normally
            // prevents it.
            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                try {
                    prepareSystemServerProfile(systemServerClasspath);
                } catch (Exception e) {
                    Log.wtf(TAG, "Failed to set up system server profile", e);
                }
            }
        }

        if (parsedArgs.invokeWith != null) {//不会进入这个分支,所以忽略
            String[] args = parsedArgs.remainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }

            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);

            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
            	//利用systemServerClass对应的路径构建对应的ClassLoader
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

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

            /*
             * Pass the remaining arguments to SystemServer.
             */
             // 将剩余参数及classLoader递交给ZygoteInit的zygoteInit函数
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

??从上面的代码可以看出,接下来的流程进入到ZygoteInit的zygoteInit函数。zygoteInit函数将根据classLoader和参数,完成不同进程所需要的初始化工作(SystemServer进程与zygote的其它子进程均将使用zygoteInit函数)。

2.6 performSystemServerDexOpt

??在分析performSystemServerDexOpt我们先来看看Os.getenv(“SYSTEMSERVERCLASSPATH”)获取的环境变量是什么,我们可以通过echo $SYSTEMSERVERCLASSPATH命令获取SYSTEMSERVERCLASSPATH 环境变量值,如下:

/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar

??了解了performSystemServerDexOpt的传入参数,我们接着继续分析下面的代码,该代码的逻辑如下:

  • 建立和installd的socket通信通道
  • 以":"分割传递过来的字符串
  • 判断是否需要dex优化services.jar和ethernet-service.jar
  • 如果需要优化,则调用dexopt优化上面的三个jar包中的需要优化的
    /**
     * Performs dex-opt on the elements of {@code classPath}, if needed. We
     * choose the instruction set of the current runtime.
     */
    private static void performSystemServerDexOpt(String classPath) {
        final String[] classPathElements = classPath.split(":");//分割字符串
        final IInstalld installd = IInstalld.Stub
                .asInterface(ServiceManager.getService("installd"));//建立和install进程通信的socket通道
        final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();

        String classPathForElement = "";
        for (String classPathElement : classPathElements) {
            // System server is fully AOTed and never profiled
            // for profile guided compilation.
            String systemServerFilter = SystemProperties.get(
                    "dalvik.vm.systemservercompilerfilter", "speed");

            int dexoptNeeded;
            try {
                dexoptNeeded = DexFile.getDexOptNeeded(
                    classPathElement, instructionSet, systemServerFilter,
                    null /* classLoaderContext */, false /* newProfile */, false /* downgrade */);//判断是否需要优化
            } catch (FileNotFoundException ignored) {
                // Do not add to the classpath.
                Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
                continue;
            } catch (IOException e) {
                // Not fully clear what to do here as we don't know the cause of the
                // IO exception. Add to the classpath to be conservative, but don't
                // attempt to compile it.
                Log.w(TAG, "Error checking classpath element for system server: "
                        + classPathElement, e);
                dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
            }

            if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {**加粗样式**
                final String packageName = "*";
                final String outputPath = null;
                final int dexFlags = 0;
                final String compilerFilter = systemServerFilter;
                final String uuid = StorageManager.UUID_PRIVATE_INTERNAL;
                final String seInfo = null;
                final String classLoaderContext =
                        getSystemServerClassLoaderContext(classPathForElement);
                final int targetSdkVersion = 0;  // SystemServer targets the system's SDK version
                try {
                	//以system权限执行dexopt优化工作
                    installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
                            instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
                            uuid, classLoaderContext, seInfo, false /* downgrade */,
                            targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null,
                            "server-dexopt");
                } catch (RemoteException | ServiceSpecificException e) {
                    // Ignore (but log), we need this on the classpath for fallback mode.
                    Log.w(TAG, "Failed compiling classpath element for system server: "
                            + classPathElement, e);
                }
            }

            classPathForElement = encodeSystemServerClassPath(
                    classPathForElement, classPathElement);
        }
    }

2.7 zygoteInit

??在前面的2.5章节我们知道parsedArgs.invokeWith属性默认为null,最后调用RuntimeInit.zygoteInit来进一步启动system_server进程。
代码定义于frameworks\base\core\java\com\android\internal\os\ZygoteInit.java,在zygoteInit中执行的主要代码逻辑如下:

  • 重定义Log输出
  • 通用的初始化
  • 启动Binder线程池
  • 应用初始化
    /**
     * The main function called when started through the zygote process. This
     * could be unified with main(), if the native code in nativeFinishInit()
     * were rationalized with Zygote startup.<p>
     *
     * Current recognized args:
     * <ul>
     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
     * </ul>
     *
     * @param targetSdkVersion target SDK version
     * @param argv arg strings
     */
    public static final 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();//重定向Log输出

        RuntimeInit.commonInit();//通用的初始化,详见章节2.8
        ZygoteInit.nativeZygoteInit();//启动Binder线程池,详见章节2.9
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//system_server应用初始化,详见章节2.10
    }

2.8 commonInit

??该代码定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中,主要是做了一些常规的初始化,从逻辑上分析主要分为如下几个方面:

  • 设置未捕获异常的处理方法
  • 设置时区
  • 重置log配置
  • 设置默认的HTTP User-agent格式,用于 HttpURLConnection
  • 设置流量统计Socket tag
    protected static final void commonInit() {
        if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

        /*
         * set handlers; these apply to all threads in the VM. Apps can replace
         * the default handler, but not the pre handler.
         */
         //对于从事应用开发的童靴来说这个是再熟悉不过的了,设置未捕获异常的处理方法
        LoggingHandler loggingHandler = new LoggingHandler();
        Thread.setUncaughtExceptionPreHandler(loggingHandler);
        Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));

        /*
         * Install a TimezoneGetter subclass for ZoneInfo.db
         */
        /*设置时区,中国时区的为Asia/Shanghai,为啥不是北京呢
         *# getprop persist.sys.timezone
		 *Asia/Shanghai
		 */
        TimezoneGetter.setInstance(new TimezoneGetter() {
            @Override
            public String getId() {
                return SystemProperties.get("persist.sys.timezone");
            }
        });
        TimeZone.setDefault(null);

        /*
         * Sets handler for java.util.logging to use Android log facilities.
         * The odd "new instance-and-then-throw-away" is a mirror of how
         * the "java.util.logging.config.class" system property works. We
         * can't use the system property here since the logger has almost
         * certainly already been initialized.
         */
        LogManager.getLogManager().reset();//重置log配置
        new AndroidConfig();

        /*
         * Sets the default HTTP User-Agent used by HttpURLConnection.
         */
        // 设置默认的HTTP User-agent格式,用于 HttpURLConnection。
        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        /*
         * Wire socket tagging to traffic stats.
         */
        //标记socket的tag,主要用于流量统计
        NetworkManagementSocketTagger.install();

        /*
         * If we're running in an emulator launched with "-trace", put the
         * VM into emulator trace profiling mode so that the user can hit
         * F9/F10 at any time to capture traces.  This has performance
         * consequences, so it's not something you want to do always.
         */
        String trace = SystemProperties.get("ro.kernel.android.tracing");
        if (trace.equals("1")) {
            Slog.i(TAG, "NOTE: emulator trace profiling enabled");
            Debug.enableEmulatorTraceOutput();
        }

        initialized = true;
    }

??这其中User-Agent是Http协议中的一部分,属于头域的组成部分,是一种向访问网站者提供你所使用的浏览器类型,操作系统,浏览器内核等信息的标识。通过这个标识,用户所访问的网站可以显示不同的排版,从而为用户提供更好的体验或者进行信息统计。

2.9 nativeZygoteInit

??一看方法名称就知道是要调用native方法进行初始化,通过调用nativeZygoteInit主要是用来启动Binder线程池的。该方法nativeZyoteInit实现在frameworks/base/core/jni/AndroidRuntime.cpp中,对应的JNI映射如下所示:

int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
            (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
        methods, NELEM(methods));
}

??通过JNI的gMethods数组,可以看出nativeZygoteInit函数对应的是JNI文件AndroidRuntime.cpp的com_android_internal_os_RuntimeInit_nativeZygoteInit函数:

/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength)
{
    SkGraphics::Init();

    // Pre-allocate enough space to hold a fair number of options.
    mOptions.setCapacity(20);

    assert(gCurRuntime == NULL);        // one per process
    gCurRuntime = this;
}

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
	//此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的,这个会详细分析的
    gCurRuntime->onZygoteInit();
}

??这里可以看到gCurRuntime是AndroidRuntime类型的指针,可是AndroidRuntime的onZygoteInit却是一个虚函数,那么就应该在其子类中实现了。那么gCurRuntime究竟指的是什么呢?

??在我们前面的篇章中介绍zygote启动过程中,在app_main.cpp的main函数中,创建出了AppRuntime对象,其逻辑如下:

//代码位于frameworks\base\cmds\app_process\app_main.cpp
int main(int argc, char* const argv[])
{
	......
	AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
	......
}

而AppRuntime 的定义也在app_main.c中其如下:

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

接着继续来看看AppRuntime的父类AndroidRuntime的代码:

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength)
{
    SkGraphics::Init();

    // Pre-allocate enough space to hold a fair number of options.
    mOptions.setCapacity(20);

    assert(gCurRuntime == NULL);        // one per process
    gCurRuntime = this;
}

??从代码可以看出,AndroidRuntime初始化时定义了gCurRuntime。gCurRuntime指向对象自身,也就是说gCurRuntime指向的是AppRuntime对象(有时候感觉继承搞起来是比较麻烦,我们驱动的同事就说看着面向对象里面那一堆堆的继承,就头疼)。

??由于SystemServer进程由zygote进程fork出来,于是system server进程中也存在gCurRuntime对象,类型为AppRuntime。至此我们知道,Native函数中gCurRuntime->onZygoteInit将调用AppRuntime中的onZygoteInit。

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();//开启binder线程,是不是有中似曾相识的熟悉感觉
    }

??ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver(),这里就不过多阐述了。这样将当前线程注册到Binder驱动程序中,这样我们创建的线程就加入了Binder线程池中,这样新创建的SyetemServer进程就支持Binder进程间通信了。

2.10 applicationInit

??继续回到ZygoteInit.java类中的applicationInit看看它做了些什么,applicationInit定义在frameworks\base\core\java\com\android\internal\os\RuntimeInit.java中,其主要逻辑如下:

  • 调用nativeSetExitWithoutCleanup(true),从而使应用退出时不调用System.exit()
  • 设置虚拟机的内存利用率参数值
  • 接着调用findStaticMain继续下一步操作
    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        //大概意思就是为true时,应用程序退出不会调用System.exit(),从而使一些关联hook可以顺利关闭
        nativeSetExitWithoutCleanup(true);

        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        //设置虚拟机的内存利用率参数值为0.75
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        final Arguments args = new Arguments(argv);//解析参数格式为Arguments 

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

        // Remaining arguments are passed to the start class's static main
        //调用findStaticMain做进一步操作,具体查看2.11章节
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

2.11 findStaticMain

??接着分析findStaticMain方法,其中传递进来的参数className是om.android.server.SystemServer ,所以其主要逻辑如下:

  • 因此通过Class.forName反射返回的cl为SystemServer类
  • 获取SystemServer类的main方法
  • 判断SystemServer类的main方法修饰符是不是public和static
  • 接着返回MethodAndArgsCaller
    /**
     * Invokes a static "main(argv[]) method on class "className".
     * Converts various failing exceptions into RuntimeExceptions, with
     * the assumption that they will then cause the VM instance to exit.
     *
     * @param className Fully-qualified class name
     * @param argv Argument vector for main()
     * @param classLoader the classLoader to load {@className} with
     */
    protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
        	// className为进行初始化工作的进程类名
            //在forkSystemServer()方法中通过硬编码初始化参数,可知该参数为com.android.server.SystemServer
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
        	//获取main方法
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
		//判断你修饰符
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        /*
         * 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.
         */
        return new MethodAndArgsCaller(m, argv);
    }

这里有一点需要重点注意的,在Android 8之前的版本都是通过直接在MethodAndArgsCaller抛出该异常,然后在ZygoteInit.java中的main方法中捕获,但是Android 8及以后都改变了这种策略是通过返回MethodAndArgsCaller,然后在main中直接调用,其逻辑如下所示,接着判断Runnable 是否为空,如果不为空则调用run方法

            if (startSystemServer) {
                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;
                }
            }

2.12 MethodAndArgsCaller

??在ZygoteInit.java中的main方法中运行r.run直捣黄龙,启动SystemServer的main方法。

    /**
     * Helper class which holds a method and arguments and can call them. This is used as part of
     * a trampoline to get rid of the initial process setup stack frames.
     */
    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
            	//根据传递过来的参数,可知此处通过反射机制调用的是SystemServer.main()方法
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

经过层层的拨山涉水,我们终于总算是进入到了SystemServer类的main()方法,但是这还只是分析system_server进程的开端,后面我们将要看看system_server进程作为Android世界的肱骨大臣究竟有何功劳,能在Android世界享有如此美誉能和zygote同生共死。下面就让我们来看看system_serveer究竟有何丰功伟绩,让我们细品!

3. SystemServer启动

??通过前面章节我们知道最后通过反射调用mMethod.invoke开启了SystemServer的彪悍人生,最终会调用到SystemServer.main()方法,还等什么让我们一探究竟。整个system_server进程启动流程图如下:
在这里插入图片描述
SystemServer.main()启动流程图示意如下,这章主要详细分析如下几个流程:
在这里插入图片描述

3.1 SystemServer.main

??无过多修饰,直接创建new一个SystemServer对象并调用其run方法。

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();//就是这么简单,直接创建并运行毫不拖泥带水的
    }

3.2 SystemServer.run

??前面main函数很简单,现在run函数就要老实干活了,其主要逻辑总结如下:

  • 初始化一些零碎事务
  • createSystemContext初始化system_server进程的context,这个是重点需要分析的
  • startBootstrapServices启动第一阶段服务
  • startCoreServices启动核心服务
  • startOtherServices启动其它服务
    private void run() {
        try {
            android.os.Process.setThreadPriority(-19);
            //这个主要是为了调试使用,打日志
            traceBeginAndSlog("InitBeforeStartServices");
            // If a device's clock is before 1970 (before 0), a lot of
            // APIs crash dealing with negative numbers, notably
            // java.io.File#setLastModified, so instead we fake it and
            // hope that time from cell towers or NTP fixes it shortly.
            //如果系统时钟早于1970,则系统强制设置从1970年开始
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                Slog.w(TAG, "System clock is before 1970; setting to 1970.");
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }

            //
            // Default the timezone property to GMT if not set.
            //
            //如果没有设置默认时区,则强制设置默认时区为GMT
            String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
            if (timezoneProperty == null || timezoneProperty.isEmpty()) {
                Slog.w(TAG, "Timezone not set; setting to GMT.");
                SystemProperties.set("persist.sys.timezone", "GMT");
            }

            // If the system has "persist.sys.language" and friends set, replace them with
            // "persist.sys.locale". Note that the default locale at this point is calculated
            // using the "-Duser.locale" command line flag. That flag is usually populated by
            // AndroidRuntime using the same set of system properties, but only the system_server
            // and system apps are allowed to set them.
            //
            // NOTE: Most changes made here will need an equivalent change to
            // core/jni/AndroidRuntime.cpp
            //设置区域,语言等选项
            if (!SystemProperties.get("persist.sys.language").isEmpty()) {
                final String languageTag = Locale.getDefault().toLanguageTag();
                SystemProperties.set("persist.sys.locale", "zh-CN");
                SystemProperties.set("persist.sys.localevar", "");
            }

            // The system server should never make non-oneway calls
            Binder.setWarnOnBlocking(true);//这几个暂时还没有搞清楚是干啥的主要,先忽略
            // The system server should always load safe labels
            PackageItemInfo.setForceSafeLabels(true);
            // Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
            SQLiteCompatibilityWalFlags.init(null);

            // Here we go!
            Slog.i(TAG, "Entered the Android system server!");
            int uptimeMillis = (int) SystemClock.elapsedRealtime();
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
            if (!mRuntimeRestart) {
                MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
            }

            // In case the runtime switched since last boot (such as when
            // the old runtime was removed in an OTA), set the system
            // property so that it is in sync. We can | xq oqi't do this in
            // libnativehelper's JniInvocation::Init code where we already
            // had to fallback to a different runtime because it is
            // running as root and we need to be the system user to set
            // the property. http://b/11463182
            //变更虚拟机的库文件,这里默认使用的是libart.so
            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

            // Mmmmmm... more memory!
            //由于system_server进程启动过程中消耗较多的虚拟机内存空间,所以先清除vm内存增长上限,供SystemServer正常启动
            VMRuntime.getRuntime().clearGrowthLimit();

            // The system server has to run all of the time, so it needs to be
            // as efficient as possible with its memory usage.
            //设置堆栈利用率为0.8,GC后会重新计算堆栈空间大小
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

            // Some devices rely on runtime fingerprint generation, so make sure
            // we've defined it before booting further.
            // 针对部分设备依赖于运行时就产生指纹信息,因此需要在开机完成前已经定义
            Build.ensureFingerprintProperty();

            // Within the system server, it is an error to access Environment paths without
            // explicitly specifying a user.
            //明确指定用户,访问环境变量前
            Environment.setUserRequired(true);

            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);//这个不是很明白,先忽略

            // Within the system server, when parceling exceptions, include the stack trace
            Parcel.setStackTraceParceling(true);//看英文意思是Parceling打包发生异常,会打印堆栈调试信息

            // Ensure binder calls into the system always run at foreground priority.
            //确保当前系统进程的binder调用,总是运行在前台优先级(foreground priority),并且设置binder最大线程数位31
            BinderInternal.disableBackgroundScheduling(true);

            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            // Prepare the main looper thread (this thread).
            //android.os.Process.setThreadPriority(
            //    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            //开启主线程Looper
            Looper.prepareMainLooper();
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

            // Initialize native services.
            //加载android_servers.so库,该库就是frameworks/base/services/core/jni生成的
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();//检测上次关机是否发生异常

            // Initialize the system context.
            createSystemContext();//重点来了,在system_server进程中创建Context,供后续启动的服务使用,具体将章节3.3

            // Create the system service manager.
            //构建SystemServiceManager对象,注意这个不是Android binder服务的大管家那个
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            
            // 将SystemServiceManager对象保存到SystemServer进程中的一个数据结构中
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        try {//启动各种层级服务
            traceBeginAndSlog("StartServices");
            startBootstrapServices();//启动系统Boot级别服务
            startCoreServices();//启动系统级别核心服务
            startOtherServices();//启动其它类型服务,主要是厂家可以根据实际情况配置的服务
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", 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);
            }
        }

        android.os.Process.setThreadPriority(
            android.os.Process.THREAD_PRIORITY_FOREGROUND);
        // Loop forever.
        Looper.loop();//启动Looper循环
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

可以看到run方法的工作主要有以下几点:

  • 对Binder进行了一些设置,这个等到之后分析Binder的时候再看;
  • performPendingShutdown:判断是否要关机或者重启;
  • createSystemContext:创建系统上下文,这个留到分析Context的时候再看;
  • 创建ServiceManager
  • 开启各种服务,然后进入Looper消息循环

3.2.1 performPendingShutdown

??这个地方不是很明白为啥要检测sys.shutdown.requested值是否为空,然后为空后需要重启终端。这个各位如果了解,也可以沟通沟通!

    private void performPendingShutdown() {
        final String shutdownAction = SystemProperties.get(
                ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
        //如果sys.shutdown.requested的值不为空则会重启终端
        if (shutdownAction != null && shutdownAction.length() > 0) {
            boolean reboot = (shutdownAction.charAt(0) == '1');

            final String reason;
            if (shutdownAction.length() > 1) {
                reason = shutdownAction.substring(1, shutdownAction.length());
            } else {
                reason = null;
            }

            // If it's a pending reboot into recovery to apply an update,
            // always make sure uncrypt gets executed properly when needed.
            // If '/cache/recovery/block.map' hasn't been created, stop the
            // reboot which will fail for sure, and get a chance to capture a
            // bugreport when that's still feasible. (Bug: 26444951)
            if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
                File packageFile = new File(UNCRYPT_PACKAGE_FILE);
                if (packageFile.exists()) {
                    String filename = null;
                    try {
                        filename = FileUtils.readTextFile(packageFile, 0, null);
                    } catch (IOException e) {
                        Slog.e(TAG, "Error reading uncrypt package file", e);
                    }

                    if (filename != null && filename.startsWith("/data")) {
                        if (!new File(BLOCK_MAP_FILE).exists()) {//不需要关机或重启
                            Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
                                       "unexpected runtime restart?");
                            return;
                        }
                    }
                }
            }
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    synchronized (this) {
                        ShutdownThread.rebootOrShutdown(null, reboot, reason);
                    }
                }
            };

            // ShutdownThread must run on a looper capable of displaying the UI.
            //这个很常见不多说了
            Message msg = Message.obtain(UiThread.getHandler(), runnable);
            msg.setAsynchronous(true);
            UiThread.getHandler().sendMessage(msg);

        }
    }

3.3 createSystemContext初始化系统上下文

??这个知识点比较重要,我们分析分析该方法,其代码逻辑如下:

  • 创建system_server进程的上下文环境
  • 设置主题样式
    private void createSystemContext() {
    	//创建system_server进程上下文环境
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

		//设置主题
        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }

3.3.1 ActivityThread.systemMain

??该类定义在frameworks/base/core/java/android/app/ActivityThread.java中,这个类大伙因该比较熟悉或者耳闻过其大名。

	ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();//单例模式
    }

    public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) {//判断是否是低内存设备,如果是低内存设备禁用硬件加速
            ThreadedRenderer.disable(true);
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true, 0);//这个在android app的启动过程中也会看到,也是这里需要重点分析的,注意这里传入的参数
        return thread;
    }

3.3.2 ActivityThread.attach

让我们接着继续分析attach函数,揭开其面纱看看其到底干了些啥!

    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {//这是Android app启动的分支,暂时不管
            ......
        } else {//分析Android app启动的时候,我还在想谁会走这条分支呢,原来是system_server进程启动会走
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());//设置system_server进程在DDMS中的名称为system_process,system_server和system_process都是同一个进程只是套了不同的马甲,各位不要被蒙骗了
            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                //先通过getSystemContext()创建系统上下文,然后通过createAppContext创建应用上下文
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                //创建Application
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                //调用Application的onCreate() 
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());

        ViewRootImpl.ConfigChangedCallback configChangedCallback
                = (Configuration globalConfig) -> {
            synchronized (mResourcesManager) {
                // We need to apply this change to the resources immediately, because upon returning
                // the view hierarchy will be informed about it.
                if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                        null /* compat */)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());

                    // This actually changed the resources! Tell everyone about it.
                    if (mPendingConfiguration == null
                            || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                        mPendingConfiguration = globalConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    }
                }
            }
        };
        //设置ViewrOotImpl回调,譬如语言,横竖变化时回调
        ViewRootImpl.addConfigCallback(configChangedCallback);
    }

??通过上述的代码分析,我们可以归纳此时的attach主要干了如下几个事情:

  • 创建系统上下文:getSystemContext() → createSystemContext() → new ContextImpl()
  • 创建应用上下文:ContextImpl.createAppContext() → new ContextImpl()
  • 添加回调configChangedCallback到ViewRootImpl

3.3.3 ActivityThread.getSystemContext

??让我们继续跟进getSystemContext,该函数比较简单直接调用ContextImpl.createSystemContext创建系统上下文。

    public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                mSystemContext = ContextImpl.createSystemContext(this);
            }
            return mSystemContext;
        }
    }

3.3.4 ContextImpl.createSystemContext

??该方法定义在frameworks/base/core/java/android/app/ContextImpl.java中,代码如下:

    static ContextImpl createSystemContext(ActivityThread mainThread) {
    	//这边new出来的LoadedApk将作为创建应用上下文的参数packageInfo
        LoadedApk packageInfo = new LoadedApk(mainThread);
        //通过ContextImpl创建系统上下文
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(packageInfo.getResources());
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
        return context;
    }

3.3.5 ContextImpl.createAppContext()创建应用上下文

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        //通过ContextImpl创建应用上下文
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(packageInfo.getResources());
        return context;
    }

??不用怀疑你的眼睛,这里的new ContextImpl的参数创建系统上下文和应用上下文是一样的,这是不是多此一举呢?createAppContext()中的参数packageInfo,就是createSystemContext()中new的LoadedApk。创建完成之后,系统上下文赋值给了ActivityThread的成员变量mSystemContext,而应用上下文只是作为函数中的局部变量临时使用。这是我的理解,不知道谷歌的工程师是不是这么认为的,或者童靴们你们有另外的理解!

3.3.6 LoadedApk.makeApplication

??让我们回头看下ActivityThread.attach中创建上下文的内容:

            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                //创建Application
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }

??接下来让我们继续分析makeApplication,该方法定义在frameworks/base/core/java/android/app/LoadedApk.java中,源码如下:

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;

        String appClass = mApplicationInfo.className;
        //这里传入的参数forceDefaultAppClass为true
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            // 此LoadedApk对象是createSystemContext时new的,mPackageName="android",大伙可以回看下
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            //有创建了一个局部应用上下文
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //创建application
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        // 将前面创建的app添加到应用列表
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        ......
        return app;
    }

3.3.7 createSystemContext总结

??createSystemContext这一章节涉及的知识面比较多,且比较重要,我们分析总结一番。在这一章节里面我们主要是创建了一个ActivityThread对象,这个对象大伙应该都不会感到陌生,然后然后执行了该对象的attach()方法,attach()方法中创建了系统上下文mSystemContext(类型为ContextImpl),并创建Application对象。系统上下文中,new了一个LoadedApk的成员变量,并将ActivityThread对象传给LoadedApk成员,后面的Application对象就是LoadedApk使用ActivityThread创建的,LoadedApk创建了Application对象后,将Application添加到ActivityThread的应用列表中。关于这个章节内容还有很多可以扩展的地方,未来会单独写一章节进行学习。

3.4 初始化SystemServiceManager系统服务管理类

??让我们收回思路,回到SystemServer中的run方法中看看创建系统服务管理类的代码。

	    // Create the system service manager.
	    //通过前面章节创建的系统上下文创建mSystemServiceManager 
	    mSystemServiceManager = new SystemServiceManager(mSystemContext);
	    //设置mSystemServiceManager 的启动相关信息
	    mSystemServiceManager.setStartInfo(mRuntimeRestart,
	            mRuntimeStartElapsedTime, mRuntimeStartUptime);
	    //将创建的mSystemServiceManager 添加到LocalServices中
	    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

这一流程比较简单,主要逻辑有如下几点:

  • 以前面章节创建的系统上下文mSystemContext初始化SystemServiceManager对象
  • 设置mSystemServiceManager 对象启动信息,主要是时间和是否是重启等
  • 将构建的mSystemServiceManager 其添加到本地服务列表中,本地服务列表是以类为key保存的一个列表,即列表中某种类型的对象最多只能有一个

3.4.1 SystemServiceManager简单分析

??该类定义在frameworks/base/services/core/java/com/android/server/SystemServiceManager.java中,主要代码逻辑如下:

/**
 * Manages creating, starting, and other lifecycle events of
 * {@link com.android.server.SystemService system services}.
 *
 * {@hide}
 */
public class SystemServiceManager {
	......
    // Services that should receive lifecycle events.
    //系统服务列表,可以看到必须系统服务必须继承SystemService
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
	
	//当前处于开机过程的哪个阶段,这个定义在SystemService中不是SystemServer中,后续会讲解
    private int mCurrentPhase = -1;
    ......
    
    /**
     * Starts a service by class name.
     *
     * @return The service instance.
     */
     //启动系统服务第一种方式,通过类名
    @SuppressWarnings("unchecked")
    public SystemService startService(String className) {
        final Class<SystemService> serviceClass;
        try {
            serviceClass = (Class<SystemService>)Class.forName(className);
        } catch (ClassNotFoundException ex) {
            Slog.i(TAG, "Starting " + className);
            throw new RuntimeException("Failed to create service " + className
                    + ": service class not found, usually indicates that the caller should "
                    + "have called PackageManager.hasSystemFeature() to check whether the "
                    + "feature is available on this device before trying to start the "
                    + "services that implement it", ex);
        }
        return startService(serviceClass);
    }

    /**
     * Creates and starts a system service. The class must be a subclass of
     * {@link com.android.server.SystemService}.
     *
     * @param serviceClass A Java class that implements the SystemService interface.
     * @return The service instance, never null.
     * @throws RuntimeException if the service fails to start.
     */
     //第二种启动系统服务方式,创建并启动系统服务,系统服务类必须继承SystemService
    @SuppressWarnings("unchecked")
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();
            Slog.i(TAG, "Starting " + name);
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);

            // Create the service.
            if (!SystemService.class.isAssignableFrom(serviceClass)) {
                throw new RuntimeException("Failed to create " + name
                        + ": service must extend " + SystemService.class.getName());
            }
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } catch (InstantiationException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service could not be instantiated", ex);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (NoSuchMethodException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (InvocationTargetException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service constructor threw an exception", ex);
            }

            startService(service);
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }
	//前面两种启动系统服务的方式,最后都会调用这个方法
    public void startService(@NonNull final SystemService service) {
        // Register it.
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

    /**
     * Starts the specified boot phase for all system services that have been started up to
     * this point.
     *
     * @param phase The boot phase to start.
     */
     // 通知系统服务到了开机的哪个阶段,会遍历调用所有系统服务的onBootPhase()函数
    public void startBootPhase(final int phase) {
        if (phase <= mCurrentPhase) {
            throw new IllegalArgumentException("Next phase must be larger than previous");
        }
        mCurrentPhase = phase;

        Slog.i(TAG, "Starting phase " + mCurrentPhase);
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
            final int serviceLen = mServices.size();
            for (int i = 0; i < serviceLen; i++) {
                final SystemService service = mServices.get(i);
                long time = SystemClock.elapsedRealtime();
                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
                try {
                    service.onBootPhase(mCurrentPhase);
                } catch (Exception ex) {
                    throw new RuntimeException("Failed to boot service "
                            + service.getClass().getName()
                            + ": onBootPhase threw an exception during phase "
                            + mCurrentPhase, ex);
                }
                warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }
    ......
}

??我们这里说mCurrentPhase表示当前处于开机过程的那个阶段,有如下几个阶段,定义在frameworks/base/services/core/java/com/android/server/SystemService.java中,如下所示:

public abstract class SystemService {
    /*
     * Boot Phases
     */
    public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?

    /**
     * After receiving this boot phase, services can obtain lock settings data.
     */
    public static final int PHASE_LOCK_SETTINGS_READY = 480;

    /**
     * After receiving this boot phase, services can safely call into core system services
     * such as the PowerManager or PackageManager.
     */
    public static final int PHASE_SYSTEM_SERVICES_READY = 500;

    /**
     * After receiving this boot phase, services can safely call into device specific services.
     */
    public static final int PHASE_DEVICE_SPECIFIC_SERVICES_READY = 520;

    /**
     * After receiving this boot phase, services can broadcast Intents.
     */
    public static final int PHASE_ACTIVITY_MANAGER_READY = 550;

    /**
     * After receiving this boot phase, services can start/bind to third party apps.
     * Apps will be able to make Binder calls into services at this point.
     */
    public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;

    /**
     * After receiving this boot phase, services can allow user interaction with the device.
     * This phase occurs when boot has completed and the home application has started.
     * System services may prefer to listen to this phase rather than registering a
     * broadcast receiver for ACTION_BOOT_COMPLETED to reduce overall latency.
     */
    public static final int PHASE_BOOT_COMPLETED = 1000;
    ......
}

3.4.2 LocalServices

??该类定义在frameworks/base/core/java/com/android/server/LocalServices.java中,逻辑so easy就是将SystemService 存放在hash表中,供后续使用。

/**
 * This class is used in a similar way as ServiceManager, except the services registered here
 * are not Binder objects and are only available in the same process.
 *
 * Once all services are converted to the SystemService interface, this class can be absorbed
 * into SystemServiceManager.
 *
 * {@hide}
 */
public final class LocalServices {
    private LocalServices() {}

    private static final ArrayMap<Class<?>, Object> sLocalServiceObjects =
            new ArrayMap<Class<?>, Object>();

    /**
     * Returns a local service instance that implements the specified interface.
     *
     * @param type The type of service.
     * @return The service object.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getService(Class<T> type) {
        synchronized (sLocalServiceObjects) {
            return (T) sLocalServiceObjects.get(type);
        }
    }

    /**
     * Adds a service instance of the specified interface to the global registry of local services.
     */
    public static <T> void addService(Class<T> type, T service) {
        synchronized (sLocalServiceObjects) {
            if (sLocalServiceObjects.containsKey(type)) {
                throw new IllegalStateException("Overriding service registration");
            }
            sLocalServiceObjects.put(type, service);
        }
    }

    /**
     * Remove a service instance, must be only used in tests.
     */
    @VisibleForTesting
    public static <T> void removeServiceForTest(Class<T> type) {
        synchronized (sLocalServiceObjects) {
            sLocalServiceObjects.remove(type);
        }
    }
}

3.5 startBootstrapServices启动引导服务

??个人感觉,能被称为引导的东西都是牛逼的东西,例如windows下的BIOS引导程序,当然这里的引导服务也不例外,基本都是Android界的实干家,牛逼的很。

    /**
     * Starts the small tangle of critical services that are needed to get
     * the system off the ground.  These services have complex mutual dependencies
     * which is why we initialize them all in one place here.  Unless your service
     * is also entwined in these dependencies, it should be initialized in one of
     * the other functions.
     */
    private void startBootstrapServices() {
        ......
        //通过mSystemServiceManager启动Installer,并且是阻塞等待与installd建立socket通道
        Installer installer = mSystemServiceManager.startService(Installer.class);
        
        ......
        
        //这个服务暂时不清楚是干啥的
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);

		//好吗,这个服务无需多言了,我是AMS重要你懂的
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer); 
        
        //PowerManagerService服务,牵涉到电源管理等等方面
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        //mPowerManagerService 已经准备就绪,AMS
        mActivityManagerService.initPowerManagement();
        
        //启动RecoverySystemService
        mSystemServiceManager.startService(RecoverySystemService.class);
        
        //不知是啥,那就只能忽略了
        RescueParty.noteBoot(mSystemContext);

        //启动LightsService服务
        mSystemServiceManager.startService(LightsService.class);
        
        //这个服务不知是啥,暂时不管了
        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
        }
        
        // 启动DisplayManagerService(必须在PMS服务启动之前)
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
        
        //划重点,初始化package manager之前,需要默认显示。阻塞,10s超时,see DisplayManagerService.onBootPhase()
        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
        traceEnd();

        // Only run "core" apps if we're encrypting the device.
        //当设备正在加密时,仅运行核心
        String cryptState = SystemProperties.get("vold.decrypt");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;
        }

        // Start the package manager.
        //启动PMS服务
        if (!mRuntimeRestart) {
            MetricsLogger.histogram(null, "boot_package_manager_init_start",
                    (int) SystemClock.elapsedRealtime());
        }
        traceBeginAndSlog("StartPackageManagerService");
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        traceEnd();
        if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
            MetricsLogger.histogram(null, "boot_package_manager_init_ready",
                    (int) SystemClock.elapsedRealtime());
        }
        // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
        // A/B artifacts after boot, before anything else might touch/need them.
        // Note: this isn't needed during decryption (we don't have /data anyways).
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            if (!disableOtaDexopt) {
                traceBeginAndSlog("StartOtaDexOptService");
                try {
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {
                    reportWtf("starting OtaDexOptService", e);
                } finally {
                    traceEnd();
                }
            }
        }

        //启动多用户服务,新建目录/data/user/
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);

        // 初始化用来缓存包资源的属性缓存,不要问我怎么知道的,按照注释翻译的
        AttributeCache.init(mSystemContext);
        
        //设置AMS
        mActivityManagerService.setSystemProcess();
        
        //直接过
        mDisplayManagerService.setupSchedulerPolicies();

        //直接过
        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));  

        // The sensor service needs access to package manager service, app ops
        // service, and permissions service, therefore we start it after them.
        // Start sensor service in a separate thread. Completion should be checked
        // before using it.
        //启动sensor服务
        mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
            TimingsTraceLog traceLog = new TimingsTraceLog(
                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            traceLog.traceBegin(START_SENSOR_SERVICE);
            startSensorService();
            traceLog.traceEnd();
        }, START_SENSOR_SERVICE);
    }

??这里可以看到startBootstrapServices会首先等待installd启动完成,然后阻塞等待和建立连接。接着会启动一系列相关联的重要服务,其中比较常见的和经常会用到的如下表格所示:

引导服务功能
Installer注意和installd的关联,这个是在系统安装apk时的一个服务类, 启动完成installer服务之后才能启动其它的系统服务,是installd的客户端和installd是C-S端架构
ActivityManagerService牛逼的AMS服务,负责四大组件的启动,切换,调度等相关工作
PowerManagerService负责Android系统中和Power相关的计算,决策系统的电源策略
LightsService管理和显示Android相关指示灯服务
DisplayManagerService用来管理Android所有显示设备服务
PackageManagerService牛逼的PKMS服务,主要用来管理apk的安装,解析,验签,删除,升级等功能
UserManagerService多用户模式管理服务
SensorServiceAndroid各种感应器管理服务!

3.6 startCoreServices启动核心服务

??无需多言,主要是启动Android系统各种核心服务,核心是啥各位应该都懂!

    /**
     * Starts some essential services that are not tangled up in the bootstrap process.
     */
    private void startCoreServices() {
        traceBeginAndSlog("StartBatteryService");
        // Tracks the battery level.  Requires LightService.
        // 启动BatteryService,用于管理电池各种状态情况
        mSystemServiceManager.startService(BatteryService.class);
        traceEnd();

        // Tracks application usage stats.
        //启动UsageStatsService服务,该服务主要用于统计应用使用情况
        traceBeginAndSlog("StartUsageService");
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        traceEnd();

        // Tracks whether the updatable WebView is in a ready state and watches for update installs.
        //启动WebViewUpdateService
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
            traceBeginAndSlog("StartWebViewUpdateService");
            mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
            traceEnd();
        }

        // Tracks cpu time spent in binder calls
        traceBeginAndSlog("StartBinderCallsStatsService");
        BinderCallsStatsService.start();
        traceEnd();
    }

??其中核心服务中常见的和其作用如下表格所示:

核心服务功能
BatteryService电源管理服务,管理电池的各种状态
UsageStatsService主要用于统计应用的使用情况,如时长,使用频率等
WebViewUpdateService用于管理webview的更新

3.7 startOtherServices启动其它服务

??该方法比较长,有近千行代码,逻辑很简单,主要是启动一系列的服务,这里就不具体列举源码了,在第四节直接对其中的服务进行一个简单分类。

    private void startOtherServices() {
		......
		mSystemServiceManager.startService(KeyChainSystemService.class);
		//启动调度策略服务
		ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
		mSystemServiceManager.startService(TelecomLoaderService.class);
	
		telephonyRegistry = new TelephonyRegistry(context);// 提供电话注册、管理服务,可以获取电话的链接状态、信号强度等
        ServiceManager.addService("telephony.registry", telephonyRegistry);
        
		mSystemServiceManager.startService(ACCOUNT_SERVICE_CLASS);//启动账号管理,密码,认证等相关的服务
		
		mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);

		mActivityManagerService.installSystemProviders();//启动provider服务
		
		mSystemServiceManager.startService(DropBoxManagerService.class);
		
		vibrator = new VibratorService(context);
        ServiceManager.addService("vibrator", vibrator);
        
		mSystemServiceManager.startService(AlarmManagerService.class);//Alarm服务

		watchdog.init(context, mActivityManagerService);//启动看门狗服务
		
		inputManager = new InputManagerService(context);//启动input输入管理服务
		wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());//WMS服务,这个也很重要
        ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
        ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
        mActivityManagerService.setWindowManager(wm);
        
		startHidlServices();//启动HIDL服务

		mSystemServiceManager.startService(VrManagerService.class);//启动vr服务

		inputManager.setWindowManagerCallbacks(wm.getInputMonitor());//启动inputManager
        inputManager.start();

		mDisplayManagerService.windowManagerAndInputReady();

		//SystemServer启动的480阶段
		mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
		
		//SystemServer启动的500阶段
		mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);

		//SystemServer启动的520阶段
		mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);

		mActivityManagerService.systemReady(() -> {
			
			mSystemServiceManager.startBootPhase(
                    SystemService.PHASE_ACTIVITY_MANAGER_READY);

	       try {
	                startSystemUi(context, windowManagerF);
	            } catch (Throwable e) {
	                reportWtf("starting System UI", e);
	            }
			}

            mSystemServiceManager.startBootPhase(
                    SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
}

??在这一阶段启动的服务太多了,就不一一列举出来,在该阶段的最后调用AMS.systemReady()启动默认Lancher进而完成了整个的开机流程。到此, System_server主线程的启动工作总算完成, 进入Looper.loop()状态,等待其他线程通过handler发送消息到主线再处理。最后附上该阶段启动的相关服务常见列表!

其他服务功能
CameraServiceProxy顾名思义摄像相关服务
AlarmManagerService定时器管理服务
InputManagerservice输入事件管理服务
WindowManagerServiceWMS窗口管理服务
VrManagerServiceVR管理服务
BluetoothService蓝牙管理服务
NotificationManagerService通知栏管理服务
DeviceStorageMonitorService存储管理相关服务
LocationManagerService定位管理服务
AudioService音频相关管理服务
LockSettingsService屏幕锁定服务,管理每个用户的相关锁屏信息
DeviceIdleControllerDoze模式的主要驱动
DevicePolicyManagerService提供一些系统级别的设置及属性
StatusBarManagerService状态栏管理服务
ClipboardService系统剪切板服务
NetworkManagementService网络管理服务
TextServicesManagerService文本服务,例如文本检查等
NetworkScoreService网络评分服务
NetworkStatsService网络状态服务
NetworkPolicyManagerService网络策略服务
WifiP2pServiceWifi Direct服务
WifiServiceWifi服务
WifiScanningServiceWifi扫描服务
RttServiceWifi相关
EthernetService以太网服务
ConnectivityService网络连接管理服务
NsdService网络发现服务
NotificationManagerService通知栏管理服务
DeviceStorageMonitorService磁盘空间状态检测服务
LocationManagerService位置服务,GPS、定位等
CountryDetectorService检测用户国家
SearchManagerService搜索管理服务
DropBoxManagerService用于系统运行时日志的存储于管理
WallpaperManagerService壁纸管理服务
AudioServiceAudioFlinger的上层管理封装,主要是音量、音效、声道及铃声等的管理
DockObserver如果系统有个座子,当手机装上或拔出这个座子的话,就得靠他来管理了
WiredAccessoryManager监视手机和底座上的耳机
UsbServiceUSB服务
SerialService串口服务
TwilightService指出用户当前所在位置是否为晚上,被UiModeManager等用来调整夜间模式。
BackupManagerService备份服务
AppWidgetService提供Widget的管理和相关服务
VoiceInteractionManagerService语音交互管理服务
DiskStatsService磁盘统计服务,供dumpsys使用
SamplingProfilerService用于耗时统计等
NetworkTimeUpdateService监视网络时间,当网络时间变化时更新本地时间。
CommonTimeManagementService管理本地常见的时间服务的配置,在网络配置变化时重新配置本地服务。
CertBlacklister提供一种机制更新SSL certificate blacklist
DreamManagerService屏幕保护
AssetAtlasService负责将预加载的bitmap组装成纹理贴图,生成的纹理贴图可以被用来跨进程使用,以减少内存。
PrintManagerService打印服务
HdmiControlServiceHDMI控制服务
FingerprintService指纹服务

4. SystemServer服务启动阶段

??通过前面的章节我们发现在SystemServer启动服务的三个阶段过程中,SystemServiceManager的startBootPhase()贯穿system_server进程以及服务的整个启动过程,基本示意图如下所示:
在这里插入图片描述
??其中最后的PHASE_BOOT_COMPLETED=1000,该阶段是发生在Boot完成和home应用启动完毕,从而完成了真正意义上的Android终端开机启动流程。系统服务更倾向于监听该阶段,而不是注册广播ACTION_BOOT_COMPLETED,从而降低系统延迟。

各个启动阶段所在源码的大致位置:

public final class SystemServer {

    private void startBootstrapServices() {
      ...
      //phase100
      mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
      ...
    }

	//重点注意,在该阶段是没有设置启动阶段标志的相关设置
    private void startCoreServices() {
      ...
    }

    private void startOtherServices() {
      ...
      //phase480 && 500
      mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
      mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
      
      //520
      mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
      ...
	mActivityManagerService.systemReady(() -> {
		......
		//550
		mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
		
		//600
        mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
		......
	}, BOOT_TIMINGS_TRACE_LOG);
}


public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        ......
        final void finishBooting() {
        	......
        // Let system services know.10000
        mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
        	......
        }
        ......
}

??如上就是Systemserver启动服务的各个阶段相关标志的设置,那么下面我们简单分析分析各个阶段主要完成的相关工作。

4.1 PHASE_START(0)

??在源码中是没有这个阶阶段的,这个是我们让更好的理解,本人强行加上去的,可以理解为system_server进程启动之后并启动SystemSever的开始阶段,在这一阶段主要创建了如下几个引导服务:

  • installer服务,主要是提供给其它服务使用
  • ActivityManagerService
  • PowerManagerService
  • RecoverySystemService
  • DisplayManagerService

4.2 PHASE_WAIT_FOR_DEFAULT_DISPLAY(100)

??进入该阶段后,将会回调4阶段创建的相关服务的onBootPhase(100)方法,然后继续创建下列相关的服务:

  • PackageManagerService
  • UserManagerService
  • OverlayManagerService
  • BatteryService
  • UsageStatsService
  • InputManagerService
  • WindowManagerService
  • NetworkWatchlistService

4.3 PHASE_LOCK_SETTINGS_READY(480)

??进入该阶段后会回调前面阶段创建服务的onBootPhase(480)方法,该阶段非常短调用完上述方法后会直接进入PHASE_SYSTEM_SERVICES_READY(500)阶段。

4.4 PHASE_SYSTEM_SERVICES_READY(500)

??进入该阶段后会回调前面阶段创建服务的onBootPhase(500)方法,并依次执行如下服务的systemReady方法:

  • WindowManagerService.systemReady():
  • PowerManagerService.systemReady():
  • PackageManagerService.systemReady():
  • DisplayManagerService.systemReady():

接下来就绪AMS.systemReady方法,这个方法非常重要!

4.5 PHASE_ACTIVITY_MANAGER_READY(550)

??该阶段中将设置AMS的mSystemReady为true表明AMS已准备就绪,进入该阶段服务能广播Intent;但是system_server主线程并没有就绪,然后继续会调用前面创建服务的onBootPhase(550)方法!接下来执行: (AMS启动native crash监控, 加载WebView,启动SystemUi等),如下:

  • mActivityManagerService.startObservingNativeCrashes()
  • mWebViewUpdateService.prepareWebViewInSystemServer
  • startSystemUi(context)
  • networkManagementF.systemReady
  • pSecServiceF.systemReady
  • networkStatsF.systemRead
  • connectivityF.systemReady
  • networkPolicyF.systemReady
  • Watchdog.getInstance().start()

4.6 PHASE_THIRD_PARTY_APPS_CAN_START(600)

??该阶段依次会调用前面阶段创建服务的onBootPhase(600),接着调用如下服务的systemRunning方法:

  • locationF.systemRunning
  • countryDetectorF.systemRunning
  • networkTimeUpdaterF.systemRunning
  • commonTimeMgmtServiceF.systemRunning
  • inputManagerF.systemRunning
  • telephonyRegistryF.systemRunning
  • mediaRouterF.systemRunning
  • mmsServiceF.systemRunning
  • incident.systemRunning

4.7 PHASE_BOOT_COMPLETED(1000)

??在经过如上一系列流程,最终调用AMS.finishBooting()时,则进入阶段PHASE_BOOT_COMPLETED(1000)。
到此,系统服务启动阶段完成就绪,system_server进程启动完成则进入Looper.loop()状态,随时待命,等待消息队列MessageQueue中的消息到来,则马上进入执行状态。


5. 总结

??system_server进程启动篇章终于告一段落了,在后续篇章中我们将要讲述zygote进程怎么否孵化普通App进程的,这个也是后续篇章的重点,也是Android启动流程系列的最后一篇。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 17:49:28  更:2021-12-01 17:51:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:20:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码