0、引言

在上篇文章《Zygote——Android系统中java世界的受精卵》中,我们提到了zygote的一个关键动作,那就是fork出system_server进程。这篇文章我们就来详细分析一下system_server的启动流程,以及都做了哪些事吧。

本文所选Android系统版本是9.0 Pie,文中所有代码片段路径在代码块第一行已经标注。文章的目的是记录自己的学习历程与心得,不做商用或盈利,凡是学习过程中学习或引用过的大佬博文或著作都会尽力标注,在此感谢各位前辈的不吝分享。本文借鉴如下:

  • 《 Android系统启动-SystemServer上篇》—— Gityuan
  • 《Android 10.0 系统启动之SystemServer进程-[Android取经之路]》—— IngresGe

1、forkSystemServer()

在上一篇文章《Zygote——Android系统中java世界的受精卵》的第二部分JAVA世界中的2.4小节,ZygoteInit.main()方法在做完准备工作后,zygote 开始fork它的第一个进程——system_server。

//pie\frameworks\base\core\java\com\android\internal\os\ZygoteInit.javapublic static void main(String[] argv) {…………zygoteServer = new ZygoteServer(isPrimaryZygote);    //创建zygote的ServerSocketif (startSystemServer) {Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);if (r != null) {    //{r == null} in the parent process, and {r != null} in the child processr.run();    //通过反射机制执行SystemServer.java的main()函数return;}}…………}

这里先是通过ZygoteServer类的构造函数,去创建zygote的LocalServerSocket:

//pie\frameworks\base\core\java\com\android\internal\os\ZygoteServer.java
ZygoteServer(boolean isPrimaryZygote) {mUsapPoolEventFD = Zygote.getUsapPoolEventFD();if (isPrimaryZygote) {mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket(Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);} else {mZygoteSocket =Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket(Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);}mUsapPoolSupported = true;fetchUsapPoolPolicyProps();    //TODO}// pie\frameworks\base\core\java\com\android\internal\os\Zygote.javastatic LocalServerSocket createManagedSocketFromInitSocket(String socketName) {int fileDesc;final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;    // "ANDROID_SOCKET_zygote"try {String env = System.getenv(fullSocketName);fileDesc = Integer.parseInt(env);} catch (RuntimeException ex) {throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);}try {FileDescriptor fd = new FileDescriptor();fd.setInt$(fileDesc);return new LocalServerSocket(fd);} catch (IOException ex) {throw new RuntimeException("Error building socket from file descriptor: " + fileDesc, ex);}}

可以看出createManagedSocketFromInitSocket()函数首先是根据socket默认前缀 "ANDROID_SOCKET_"和该socket名称"zygote",拼接成环境变量的key = "ANDROID_SOCKET_zygote" ,然后以该key值从环境变量中获取目标socket的文件描述符fd。(这个环境变量的键值在init阶段解析init.zygote.rc、读取并启动zygote这个service下面的socket(socket zygote stream 660 root system),在目标设备创建/dev/socket/zygote 这个文件时,就已经以"ANDROID_SOCKET_zygote"为键,创建该socket的文件描述符fd为值,存储到环境变量中了。)这里获取到目标socket的文件描述符后,就用其创建了LocalServerSocket。

以上这些准备好了之后,就要做forkSystemServer这个重要的动作了,鉴于该函数挺长,所以依然分割开来解析。

1.1、参数准备

// pie\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {long capabilities = posixCapabilitiesAsBits(OsConstants.CAP_IPC_LOCK,OsConstants.CAP_KILL,OsConstants.CAP_NET_ADMIN,OsConstants.CAP_NET_BIND_SERVICE,OsConstants.CAP_NET_BROADCAST,OsConstants.CAP_NET_RAW,OsConstants.CAP_SYS_MODULE,OsConstants.CAP_SYS_NICE,OsConstants.CAP_SYS_PTRACE,OsConstants.CAP_SYS_TIME,OsConstants.CAP_SYS_TTY_CONFIG,OsConstants.CAP_WAKE_ALARM,OsConstants.CAP_BLOCK_SUSPEND);StructCapUserHeader header = new StructCapUserHeader(OsConstants._LINUX_CAPABILITY_VERSION_3, 0);StructCapUserData[] data;try {data = Os.capget(header);} catch (ErrnoException ex) {throw new RuntimeException("Failed to capget()", ex);}capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);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,3011","--capabilities=" + capabilities + "," + capabilities,"--nice-name=system_server","--runtime-args","--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,"com.android.server.SystemServer",};…………
}

这里主要做的工作就是为后面fork出system_server进程准备启动参数。首先是通过posixCapabilitiesAsBits()函数配置一个long类型的(POSIX capability)能力参数(说人话就是配置system_server进程可以拥有的能力或权限,即能做哪些事),然后和其他命令行参数一起组成启动system_server所需要传入的字符串数组类型的参数args。

其中的OsConstants类位于pie\libcore\luni\src\main\java\android\system\OsConstants.java中,这个类把CAP_KILL这些静态常量都设置为0,源码注释:A hack to avoid these constants being inlined by javac......because we want to initialize them at runtime.大概意思就是说,这样做是不想在静态编译(javac)的时候这些常量被内联进去,而是想借用native方法在运行时去初始化。具体操作就是在该Java类的静态块里面调用了一个native接口,该native接口在运行时才会通过GetStaticFieldID()和SetStaticIntField()函数去给这些静态常量设置具体的值。该native方法位于pie\libcore\luni\src\main\native\android_system_OsConstants.cpp中,而这些值的具体定义是在<linux/capability.h>中,而这个文件位于pie\bionic\libc\kernel\uapi\linux\capability.h。这些原文件中对每个数值定义都有详细的说明注释,有兴趣可以看看这些注释。看明白这些数值的的定义范围,返回来就看得懂函数posixCapabilitiesAsBits()通过传入的不定参数,对system_server进程能力(Capabilities)的配置过程了:

/**
*kitkak\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
* Gets the bit array representation of the provided list of POSIX capabilities.
*/
private static long posixCapabilitiesAsBits(int... capabilities) {long result = 0;for (int capability : capabilities) {if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {throw new IllegalArgumentException(String.valueOf(capability));}result |= (1L << capability);}return result;
}

其无非就是通过位操作,将目标long类型整数的二进制形式中,能力(Capabilities)使能所代表的位置为1而已。比如不定参数的第一个常量CAP_KILL的数值为5,则代码将long类型的1有符号左移五位,其他不同的数值也是类似左移不同的位数,最终通过 |= 操作整合出目标数值。

1.2、参数解析与标识置位

// pie\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {…………ZygoteArguments parsedArgs;int pid;try {//将args存储到zygote命令缓冲区中,这个ZygoteCommandBuffer是一个用于Zygote命令的本机可访问的缓冲区。//设计支持重复fork的应用程序,而不干预内存分配,从而保持zygote内存尽可能稳定ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);try {   //单例模式解析参数parsedArgs = ZygoteArguments.getInstance(commandBuffer);} catch (EOFException e) {throw new AssertionError("Unexpected argument error for forking system server", e);}commandBuffer.close();    //及时释放本地资源,避免命令重复调用Zygote.applyDebuggerSystemProperty(parsedArgs);Zygote.applyInvokeWithSystemProperty(parsedArgs); //--invoke-with=?if (Zygote.nativeSupportsMemoryTagging()) {/* The system server has ASYNC MTE by default, in order to allow system services to specify * their own MTE level later, as you can't re-enable MTE once it's disabled. */String mode = SystemProperties.get("arm64.memtag.process.system_server", "async");if (mode.equals("async")) {parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;} else if (mode.equals("sync")) {parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_SYNC;} else if (!mode.equals("off")) {// When we have an invalid memory tag level, keep the current level.parsedArgs.mRuntimeFlags |= Zygote.nativeCurrentTaggingLevel();Slog.e(TAG, "Unknown memory tag level for the system server: \"" + mode + "\"");}} else if (Zygote.nativeSupportsTaggedPointers()) {//Enable pointer tagging in the system server. Hardware support for this is present in all ARMv8 CPUsparsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;}/* Enable gwp-asan on the system server with a small probability. This is the same* policy as applied to native processes and system apps. */parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;if (shouldProfileSystemServer()) {parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;}…………
}

这里主要是先将1.1部分准备的参数args存储到ZygoteCommandBuffer这个命令缓冲区中,然后通过ZygoteArguments.getInstance()接口,获取单例模式的ZygoteArguments类的实例。之后ZygoteArguments类的构造函数调用parseArgs()函数对这些zygote命令参数进行解析,最后根据一些配置对参数解析出来的结果对象parsedArgs的mRuntimeFlags成员进行标识位置位。

其中获取单例模式的ZygoteArguments的实例时,在构造函数中调用parseArgs()去解析参数的过程:

//pie\frameworks\base\core\java\com\android\internal\os\ZygoteArguments.javaprivate ZygoteArguments(ZygoteCommandBuffer args, int argCount)throws IllegalArgumentException, EOFException {parseArgs(args, argCount);}public static ZygoteArguments getInstance(ZygoteCommandBuffer args)throws IllegalArgumentException, EOFException {int argCount = args.getCount();return argCount == 0 ? null : new ZygoteArguments(args, argCount);}

1.3、真正的fork动作

// pie\frameworks\base\core\java\com\android\internal\os\ZygoteInit.javaprivate static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {…………int pid;try {…………pid = Zygote.forkSystemServer(parsedArgs.mUid, parsedArgs.mGid,parsedArgs.mGids,parsedArgs.mRuntimeFlags,null,parsedArgs.mPermittedCapabilities,parsedArgs.mEffectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}…………}

这里直接去找Zygote.forkSystemServer()方法:

//pie\frameworks\base\core\java\com\android\internal\os\Zygote.javastatic int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {ZygoteHooks.preFork();    //停掉守护线程,停掉当前进程的所有的线程,zygote每次fork前调用int pid = nativeForkSystemServer(uid, gid, gids, runtimeFlags, rlimits,permittedCapabilities, effectiveCapabilities);Thread.currentThread().setPriority(Thread.NORM_PRIORITY);    //设置当前线程优先级//每次调用preFork()后,都会在子进程上调用postForkChild(),//并且都会在父进程和子进程上调用postForkCommon(),//子进程调用postForkCommon()在postForkCommon()之后ZygoteHooks.postForkCommon();return pid;}

这里做了fork前的准备后,主要就是通过jni去调用了nativeForkSystemServer()函数:

//pie\frameworks\base\core\jni\com_android_internal_os_Zygote.cpp
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 permitted_capabilities,jlong effective_capabilities) {//初始化USAP相关的一个vectorstd::vector<int> fds_to_close(MakeUsapPipeReadFDVector()), fds_to_ignore(fds_to_close);fds_to_close.push_back(gUsapPoolSocketFD);if (gUsapPoolEventFD != -1) {fds_to_close.push_back(gUsapPoolEventFD);fds_to_ignore.push_back(gUsapPoolEventFD);}if (gSystemServerSocketFd != -1) {fds_to_close.push_back(gSystemServerSocketFd);fds_to_ignore.push_back(gSystemServerSocketFd);}pid_t pid = zygote::ForkCommon(env, true, fds_to_close, fds_to_ignore, true);    //fork动作if (pid == 0) {/在子进程中进行一些system_server相关配置,有兴趣的话去详细看看SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,permitted_capabilities, effective_capabilities,MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr, false, nullptr, false, false);} else if (pid > 0) {ALOGI("System server process %d has been created", pid);gSystemServerPid = pid;int status;//在父进程zygote中使用waitpid()函数以及WNOHANG这个选项,监控子进程的结束情况,//监控到system_server进程结束时,需要重启zygote。//waitpid()函数参考https://www.cnblogs.com/zhaihongliangblogger/p/6367041.htmlif (waitpid(pid, &status, WNOHANG) == pid) {ALOGE("System server process %d has died. Restarting Zygote!", pid);RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");}if (UsePerAppMemcg()) {    //检测是否挂载了memcgif (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {ALOGE("couldn't add process %d into system memcg group", pid);}}}return pid;
}

这里重点就是通过ForkCommon()函数fork子进程,然后通过SpecializeCommon()函数对子进程做一些配置。这里需要注意的是我注释里写到的,zygote会监控system_server进程,当system_server进程因为一些原因退出时,需要重启zygote以重新启动system_server。这里主要来看一下ForkCommon()函数的fork过程:

// pie\frameworks\base\jni\com_android_internal_os_Zygote.cpp
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,const std::vector<int>& fds_to_close,const std::vector<int>& fds_to_ignore,bool is_priority_fork,bool purge) {SetSignalHandlers();    //为zygote管理子进程配置信号SIGCHLD/SIGHUP//指定ZygoteFailure函数,其用来向runtime报告致命错误auto fail_fn = std::bind(zygote::ZygoteFailure, env, is_system_server ? "system_server" : "zygote", nullptr, _1);//在fork期间临时阻塞SIGCHLD。SIGCHLD处理程序可能会记录日志,BlockSignal(SIGCHLD, fail_fn); //这将导致我们关闭的日志fd被重新打开。会导致失败,因为不允许列出fd__android_log_close();         //在开始计算文件描述符列表之前,关闭所有与日志记录相关的fdAStatsSocket_close();if (gOpenFdTable == nullptr) { //如果这是zygote的第一次fork,则创建一个打开的FD表,验证文件受支持的类型和允许列表gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, fail_fn);} else {    //如果不是,则检查打开的文件是否没有更改,不希望并且未来会禁止打开新的文件。gOpenFdTable->Restat(fds_to_ignore, fail_fn);    //目前的做法是,如果通过了上面的Create检测,则允许打开新的文件}android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();if (purge) {           //清除未使用的本机内存,以减少与子进程的错误共享。通过减少与子进程共享的libc_malloc区域的大小,  mallopt(M_PURGE, 0); //当malloc在fork之后调整它所管理的每个页面上的元数据时,可以减少转换到私有脏状态的页面数量}pid_t pid = fork();    //核心的fork动作if (pid == 0) {        //子进程if (is_priority_fork) {setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);} else {setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);}PreApplicationInit();DetachDescriptors(env, fds_to_close, fail_fn);    //通过dup3()函数清除那些需要立即关闭的文件描述符ClearUsapTable();                                 //清除USAP进程表gOpenFdTable->ReopenOrDetach(fail_fn);            //重新打开所有剩余的打开的文件描述符,这样它们就不会通过fork与zygote共享android_fdsan_set_error_level(fdsan_error_level);gSystemServerSocketFd = -1;} else {               //父进程ALOGD("Forked child process %d", pid);}UnblockSignal(SIGCHLD, fail_fn);                    //fork结束后打开阻塞,对应上面的BlockSignal()return pid;
}

1.4、fork后的扫尾工作

// pie\frameworks\base\core\java\com\android\internal\os\ZygoteInit.javaprivate static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {…………//由于fork()函数完成任务后返回的位置不确定,如果在子进程中,fork函数返回0;//如果在父进程中,fork返回新创建子进程的进程IDif (pid == 0) {    if (hasSecondZygote(abiList)) {            //通过比较设备ABI列表和受精卵列表来确定这一点,waitForSecondaryZygote(socketName);    //如果这个受精卵支持该设备支持的所有abi,就不会有另一个受精卵}zygoteServer.closeServerSocket();    //fork出来的子进程中不会用到zygoteServer这个socket,所以要关掉return handleSystemServerProcess(parsedArgs);    //做一些fork system_server的扫尾工作}return null;}

在上一小节的native fork动作结束返回后,这里需要通过handleSystemServerProcess()方法来做一些system_server进程的收尾动作:

// pie\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {Os.umask(S_IRWXG | S_IRWXO);    //进程权限设置为0077,这样新文件和目录将默认为所有者权限if (parsedArgs.mNiceName != null) {    //参数准备部分的"--nice-name=system_server"Process.setArgV0(parsedArgs.mNiceName);    //进程名设置为system_server}//环境变量SYSTEMSERVERCLASSPATH=/system/framework/services.jar://                        /system/framework/ethernet-service.jar://                        /system/framework/wifi-service.jar:…………final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");if (systemServerClasspath != null) {if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {try {Log.d(TAG, "Preparing system server profile");prepareSystemServerProfile(systemServerClasspath);    //debug或eng模式下准备system_server的profile文件} catch (Exception e) {Log.wtf(TAG, "Failed to set up system server profile", e);}}}if (parsedArgs.mInvokeWith != null) {    //TODOString[] args = parsedArgs.mRemainingArgs;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.mInvokeWith, parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,VMRuntime.getCurrentInstructionSet(), null, args);throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");} else {    //一般system_server走这个分支ClassLoader cl = getOrCreateSystemServerClassLoader(); //为system_server创建类加载器if (cl != null) {Thread.currentThread().setContextClassLoader(cl);  //为当前线程设置上下文类加载器}return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);}}

继续追踪ZygoteInit.zygoteInit() 方法:

// pie\frameworks\base\core\java\com\android\internal\os\ZygoteInit.javapublic static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,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();    //将java的system.out和system.err log输出流重定向到AndroidPrintStreamRuntimeInit.commonInit(); //设置log配置、通过persist.sys.timezone的属性值设置时区、设置默认的HTTP User-agent格式到http.agent属性    //通过JNI调用AndroidRuntime的成员gCurRuntime(即app_process.cpp中)的onZygoteInit()函数,ZygoteInit.nativeZygoteInit();     //主要完成创建binder的工作return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv, classLoader);}

追踪RuntimeInit.applicationInit()方法:

// pie\frameworks\base\core\java\com\android\internal\os\RuntimeInit.javaprotected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) {…………//从前面准备的参数中解析出"com.android.server.SystemServer"赋值给args.startClassfinal Arguments args = new Arguments(argv);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);    //对应上面ZygoteInit的traceBegin()//有了类的全限定名,通过反射机制找到SystemServer.java的main()方法return findStaticMain(args.startClass, args.startArgs, classLoader);}protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {…………    //省略通过反射机制寻找main方法的过程return new MethodAndArgsCaller(m, argv);}//将main方法封装到Runnable实例中返回,最终返回给第1节一开始的Runnable r,然后通过r.run()执行该main方法static class MethodAndArgsCaller implements Runnable {private final Method mMethod;private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}public void run() {try {mMethod.invoke(null, new Object[] { mArgs });} catch (IllegalAccessException ex) {…………}}}

总结一下1.4小节主要做了:

  1. 对fork出来的新进程的权限设定;
  2. 进程命名为system_server;
  3. 创建类加载器加载system_server的java类;
  4. 通过反射机制找到SystemServer.java的main函数,并封装到Runnable r;
  5. 方法return到文章最开始,在system_server进程中通过r.run()执行该main方法,以启动SystsmServer;

到此为止,zygote进程fork system_server进程的动作就结束了,我说的只是fork动作,system_server进程的主要功能部分还没开始呢,这个我们在第二大节再看。第一大节的调用流程如下:

2、SystemServer.main()

// pie\frameworks\base\services\java\com\android\server\SystemServer.javapublic static void main(String[] args) {new SystemServer().run();}public SystemServer() {    //构造方法mFactoryTestMode = FactoryTest.getMode(); //检测厂测模式// 记录进程的启动的时间和启动次数mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();mRuntimeStartUptime = SystemClock.uptimeMillis();Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime);mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed")); //用于检测runtime是否重启了}

接下来就是在system_server进程中,执行SystemServer这个Java类的main()方法,开始了system_server这个进程的主要功能。如上代码所示,静态main()方法首先调用该类的构造函数获创建一个SystemServer类的对象,然后执行该对象的run方法。

2.1、run()

// pie\frameworks\base\services\java\com\android\server\SystemServer.javaprivate void run() {TimingsTraceAndSlog t = new TimingsTraceAndSlog();try {t.traceBegin("InitBeforeStartServices");// 记录进程启动的时间信息SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);//如果时区属性没有设置,则设置为GMTString timezoneProperty = SystemProperties.get("persist.sys.timezone");if (!isValidTimeZoneId(timezoneProperty)) {Slog.w(TAG, "persist.sys.timezone is not valid (" + timezoneProperty + "); setting to GMT.");SystemProperties.set("persist.sys.timezone", "GMT");}//设置语言属性if (!SystemProperties.get("persist.sys.language").isEmpty()) {final String languageTag = Locale.getDefault().toLanguageTag();SystemProperties.set("persist.sys.locale", languageTag);SystemProperties.set("persist.sys.language", "");SystemProperties.set("persist.sys.country", "");SystemProperties.set("persist.sys.localevar", "");}Binder.setWarnOnBlocking(true); // Binder阻塞时发出警告PackageItemInfo.forceSafeLabels(); //system_server应该总是加载安全标签SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL; //设置SQLiteGlobal的默认同步模式SQLiteCompatibilityWalFlags.init(null); //直到settingsProvider初始化之前,关闭SQLiteCompatibilityWalFlagsSlog.i(TAG, "Entered the Android system server!");final long uptimeMillis = SystemClock.elapsedRealtime();EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);if (!mRuntimeRestart) {    //如果是第一次启动runtime(即开机),则记录时间日志FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START,uptimeMillis);}//如果上次启动后,runtime发生了切换,那么就设置该属性值以同步。(比如系统升级后运行时库从libdvm.so切换为libart.so)//不能在libnativehelper目录下的JniInvocation::Init中设置的原因是,我们需要system权限来设置而非rootSystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());VMRuntime.getRuntime().clearGrowthLimit(); //清除vm内存增长上限,由于启动过程需要较多的虚拟机内存空间Build.ensureFingerprintProperty();  //针对部分设备依赖于运行时就产生指纹信息,因此需要在开机完成前已经定义Environment.setUserRequired(true); //访问环境变量前,需要明确地指定用户BaseBundle.setShouldDefuse(true); //在system_server中,任何传入的Bundle都应该被解除,以避免抛出BadParcelableExceptionParcel.setStackTraceParceling(true); //当打包异常时,信息需要包含堆栈跟踪BinderInternal.disableBackgroundScheduling(true); //确保当前系统进程的binder调用,总是运行在前台优先BinderInternal.setMaxThreads(sMaxBinderThreads); //设置system_server中binder线程的最大数量:31准备主线程lopper,即在当前线程运行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);SystemServiceRegistry.sEnableServiceNotFoundWtf = true;System.loadLibrary("android_servers");    //加载libandroid_runtime.so,初始化native services//debug版本相关操作initZygoteChildHeapProfiling();if (Build.IS_DEBUGGABLE) {spawnFdLeakCheckThread();}performPendingShutdown(); //检测系统是否需要重启,该调用可能不会返回createSystemContext(); // 创建system_server进程的上下文信息ActivityThread.initializeMainlineModules(); //调用每个进程主线模块初始化ServiceManager.addService("system_server_dumper", mDumper); //设置system_server_dumper服务mDumper.addDumpable(this);//创建SystemServiceManagermSystemServiceManager = new SystemServiceManager(mSystemContext);mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);mDumper.addDumpable(mSystemServiceManager);//将mSystemServiceManager添加到本地服务的成员sLocalServiceObjectsLocalServices.addService(SystemServiceManager.class, mSystemServiceManager);//为可以并行化的init任务准备线程池SystemServerInitThreadPool tp = SystemServerInitThreadPool.start();mDumper.addDumpable(tp);//为系统服务器加载预安装的系统字体,以便WindowManagerService等可以开始使用Typeface。//注意字体不仅在文本渲染中是必需的,在一些文本操作中也是必需的(例如textutil . makesafeforpresentation())if (Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {Typeface.loadPreinstalledSystemFontMap();}if (Build.IS_DEBUGGABLE) {    //debug模式连接jvmti代理String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");if (!jvmtiAgent.isEmpty()) {int equalIndex = jvmtiAgent.indexOf('=');String libraryPath = jvmtiAgent.substring(0, equalIndex);String parameterList =jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());// Attach the agent.try {Debug.attachJvmtiAgent(libraryPath, parameterList, null);} catch (Exception e) {Slog.e("System", "*************************************************");Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);}}}} finally {t.traceEnd();  // InitBeforeStartServices}RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf); //Setup the default WTF handlertry {t.traceBegin("StartServices");startBootstrapServices(t); //启动引导级别服务startCoreServices(t);      //启动核心服务startOtherServices(t);     //启动其他服务} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}StrictMode.initVmDefaults(null);if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {final long uptimeMillis = SystemClock.elapsedRealtime();FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_READY,uptimeMillis);final long maxUptimeMillis = 60 * 1000;if (uptimeMillis > maxUptimeMillis) {    //设备启动过程超过1分钟Slog.wtf(SYSTEM_SERVER_TIMING_TAG,"SystemServer init took too long. uptimeMillis=" + uptimeMillis);}}Looper.loop();    //线程一直循环下去throw new RuntimeException("Main thread loop unexpectedly exited"); //循环线程异常退出时抛出异常}

run()方法主要就是做好各种准备工作后,通过startBootstrapServices()、startCoreServices()、startCoreServices()这三个方法,分阶段启动adroid系统运行过程中离不开的各种服务。其中startBootstrapServices()方法中启动的服务要么是后面其他服务的启动会依赖它,要么是控制与用户的关键交互,所以这些需要尽早启动。startCoreServices()方法从名字就可以看出,启动的依然是一些核心重要的服务,但是这些服务相对独立,且与其他服务不会有启动先后依赖,所以这些服务放在这里启动。startCoreServices()方法篇幅很长,毕竟除了前面这些已经启动的,剩下还有很多服务需要启动,放在后面启动并不代表它们不重要,相反这里依然有很多关键的服务,平时的系统问题调试经常会遇到它们,只是它们的启动优先级不高而已。

总的来说,所有的这些服务都是分阶段,有先后顺序来启动的。我们就不把这三个方法拿出来一行一行看了,因为它们做的事都差不多,主要就是通过mSystemServiceManager.startService()方法,一个一个按顺序启动这些服务而已。所以我们不妨把这三个方法糅合成一个大的方法,从宏观上看这些服务是如何分阶段来启动的。在此之前,我们不得不先得理清楚SystemServiceManager、ServiceManager、SystemService这几个概念,否则是没法理解到分阶段的含义,以及服务是如何启动的了。

2.2、服务启动与管理

首先是SystemServiceManager、ServiceManager、SystemService这几个东东,一开始学习的时候,我都快要被它们几个绕晕了。不过不要慌,要挑战的排好队,一个一个来。

这里就要说一下我为什么喜欢画图了,因为画图总是能把问题直观的表现出来,复杂的问题通过画图可以梳理清楚内在联系,下面我们就通过上面这张图来解释一下,这些东西之间的关系。

首先来看上图中左上角部分,可以看到Android frameworks层众多服务都是直接或间接继承自SystemService这个抽象类的,这里的间接是指比如AMS(ActivityManagerService)就是通过内部静态类LifeCycle继承SystsmService类的。SystsmService类中有个抽象方法onStart(),所有继承自SystemService类的服务,都必须重写onStart()方法,在这些服务一个个创建好对象并启动的时候,就是通过这个onStart()方法来启动服务自身内部逻辑的。

// pie\frameworks\base\services\core\java\com\android\server\SystemService.java
public abstract class SystemService {…………/*** Called when the dependencies listed in the @Service class-annotation are available and after the chosen start phase.* When this method returns, the service should be published.*/public abstract void onStart();
}

然后再来看上图中左下角部分,我们跟随箭头从下往上看。首先就是我们本文第一大节所解析的,zygote进程fork出第一个进程system_server后,在这个新进程中执行SystemServer这个java类的main()方法,然后辗转调用该类的run()方法,以开始执行system_server进程的真实功能。在2.2小节的run()方法代码中出现的语句:mSystemServiceManager = new SystemServiceManager(mSystemContext);中,这个SystemServiceManager类就是用来管理继承自SystemService类的各类服务的实例的,也就是上图中中间红色部分所代表的一个个服务的实例。注意这里是指在system_server进程内部的管理,即进程内的服务创建、服务启动、服务注册。

而run()方法中的startBootstrapServices()、startCoreServices()、startCoreServices()这三个方法,一直都在重复mSystemServiceManager.startService()这个动作。startService()方法辗转调用自己重载的三个方法,第一个方法是根据服务类的全限定名(比如”com.android.server.job.JobSchedulerService“),通过反射机制先获取到该类的类类型。第二个方法确认该类类型是继承自SystemService类后,通过反射机制调用该类的构造方法,创建该类的实例,即上图中中间红色部分。第三个方法则是直接调用该服务对象的onStart()方法,以启动各个服务自身的逻辑。(这里通过反射机制去创建实例,而不是直接去new,主要是为了避免编译时,如果该服务找不到,或者编译环境内不包含该服务时的编译异常。)

// pie\frameworks\base\services\core\java\com\android\server\SystemServiceManager.javapublic 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("…………", ex);}return startService(serviceClass);}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);if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException(…………);}final T service;try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (……Exception ex) {…………} startService(service);return service;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}}public void startService(@NonNull final SystemService service) {mServices.add(service); // Register it.long time = SystemClock.elapsedRealtime(); // Start it.try {service.onStart();} catch (RuntimeException ex) {…………}warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");}

接着再来看上图中右上角橙黄色部分,前面提到的onStart()方法,各种服务在重写该方法的时候,一般都会调用一个叫做publishBinderService()的方法。这个方法主要的功能就是调用 ServiceManager.addService()方法,通过binder通信将当前服务注册到一个叫做servicemanager的进程中。

// pie\frameworks\base\services\core\java\com\android\server\SystemService.javaprotected final void publishBinderService(String name, IBinder service) {publishBinderService(name, service, false);}/*** Publish the service so it is accessible to other services and apps.*/protected final void publishBinderService(String name, IBinder service,boolean allowIsolated) {publishBinderService(name, service, allowIsolated, DUMP_FLAG_PRIORITY_DEFAULT);}protected final void publishBinderService(String name, IBinder service,boolean allowIsolated, int dumpPriority) {ServiceManager.addService(name, service, allowIsolated, dumpPriority);}

那为什么要注册到servicemanager进程呢?那当然是因为上面创建并启动的一个个服务对象,都是在system_server进程中,更具体的说是在system_server进程虚拟机的堆中,那其他进程就没办法依赖或者使用这些服务了。为了使得其他进程也能调用这些服务,我们把这些服务注册到这个单独的进程中,这个进程任务也很简单,就是管理好大家注册过来的服务,然后其他进程想要访问的时候提供就可以了。

现在我们来看看上图中右上角浅绿色部分的servicemanager,注意不是ServiceManager(区分大小写)。servicemanager是一个系统进程,它是在init.rc中由init进程启动的。如其名称所述,它的主要功能主要是管理各种服务,注意这里指的在进程间管理。其接收binder方式的进程间通信,对外主要暴露两个接口:注册服务和查询服务。其他进程想要调用,就需要通过binder方式,先与servicemanager进程建立binder连接,然后完成对注册或查询接口的调用。

而ServiceManager这个java类通过调用ServiceManagerNative.java走到native,通过binder与servicemanager进程建立通信,然后完成服务注册等动作。其作用就是提供servicemanager进程在java层的调用API,相当于servicemanager进程在java层的一个代理。

// pie\frameworks\base\services\core\java\com\android\server\SystemService.java
public abstract class SystemService {    /*** Called on each phase of the boot process. Phases before the service's start phase* (as defined in the @Service annotation) are never received.*/public void onBootPhase(int phase) {}
}

最后我们再看看上图中右下角部分, SystemService类中有一个onBootPhase()方法,大部分服务也都会重写该方法。首先我们将系统中众多服务一个一个按顺序的启动过程,划分了几个阶段。而这几个不同的阶段,就表示着哪些服务已经启动好了,哪些服务准备就绪了。其中某些服务的功能需要依赖其他服务完全启动后,才可以执行。这些服务重写该方法,就是为了在启动的不同阶段回调该方法做不同的任务。

当然run()方法整个调用执行过程中(包括子方法),除了通过startService()启动不同的服务、回调onBootPhase()方法外,还有对一些服务特殊接口的调用。如上图右下角,在PHASE 500到PHASE 520之间,调用WMS、AMS、PKMS、DMS的systemReady()方法;在PHASE 550到PHASE 600之间,调用startSystemUi()方法,调用一些服务的systemReady(),启动Watchdog;以及最后的PHASE 600到PHASE 1000之间,调用一些服务的systemRunning()方法,以及AMS在finishBooting()方法中进入使PHASE=1000。

3、结语

本文主要跟踪了system_server这个进程从诞生到它的功能执行的整个过程,未分析到内容的后面又更深入的认识后再来补充。文中出现的两张图请见: Pie_system_server | ProcessOn免费在线作图,在线流程图,在线思维导图 |

Android9.0(Pie) system_server进程学习相关推荐

  1. linux pipe 命名管道,linux 进程学习笔记-named pipe (FIFO)命名管道

    与"无名管道"不同的是,FIFO拥有一个名称来标志它,所谓的名称实际上就是一个路径,比如"/tmp/my_fifo",其对应到磁盘上的一个管道文件,如果我们用f ...

  2. android9.0 uri,Android9.0源码学习 - Launcher Activity(一)

    那就我看code的情况,需要知道的概念有:Tasks&Back Stack Lifecycle LauncherMode(standard/singleTop/singleTask/singl ...

  3. android-9.0主要有哪些新功能(Pie)

    Android 9 功能和 API: Android 9.0 利用人工智能技术,让手机变得更智能.更快,并且还可以随着用户的使用习惯进行调整. 利用 Wi-Fi RTT 进行室内定位 Android ...

  4. android serialport new 软件退出_基于Android9.0,了解Android启动流程

    先记住四个进程和三种方式. **四个进程** 1.Launcher进程 2.system_server进程 3.App进程 4.Zygote进程 **三种方式** 1.Binder方式 2.Socke ...

  5. 基于Android9.0,了解启动流程

    先记住四个进程和三种方式. 四个进程 1.Launcher进程 2.system_server进程 3.App进程 4.Zygote进程 三种方式 1.Binder方式 2.Socket方式 3.Ha ...

  6. android pie mi 3 tab,前沿科技:三星Galaxy Tab S3和Tab A(2017)正在获得Android 9.0 Pie更新

    互联网是高科技的产物,是历史发展.社会进步.人类智慧的结晶:是人类迄今所拥有的容量最大.内容最广.传递速度最快的信息中心.全球每天有四亿人使用互联网,上网人数占世界人口的百分之6.互联网为我们了解时事 ...

  7. 小米2s Android pie,Android 9.0 Pie正式版发布,小米MIX 2S率先升级,国内第一款!

    2018-8-8 12:22 [天极网手机频道]期待已久的的Android 9.0正式版终于到来,对应的甜品名称也正式揭晓--Android 9.0 Pie(派).与往年一样,谷歌亲儿子Pixel系列 ...

  8. Android9.0以上系统安装Edxposed

    说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除 作者:zhu6201976 一.背景说明 Android9.0以前,Xposed框架可通过apk进行快速安装,github地址: Git ...

  9. android9是最新版本,Android9.0正式版发布,你的手机升级到主流Android8.0系

    原标题:Android9.0正式版发布,你的手机升级到主流Android8.0系 今天凌晨,谷歌正式推送Android9.0更新,这款最新的安卓系统被命名为Android Pie,Pie意义为&quo ...

最新文章

  1. [转]Passing data between pages in JQuery Mobile mobile.changePage
  2. [转] 在Mac上搭建React Native开发环境
  3. SRV记录用来标识某台服务器使用了某个服务,常见于微软系统的目录管理——深入的话需要去折腾Azure Active Directory...
  4. 在C++中调用DLL中的函数
  5. Spring项目包变文件夹
  6. 不小心发现谷歌 Firebase 消息服务的漏洞,获奖3万+美元
  7. python中开根号函数_用二分法定义平方根函数(Bisection method Square Root Python)
  8. 四级网络工程师笔记-计算机网络(中)
  9. 如果你的 pip 命令不能用,你可以这样解决
  10. 【露】UK大冒险之——变身小小小黄鸡
  11. c语言计算增长率的程序,国民生产总值增长率计算的编程设计
  12. PHP中文转换为数组,PHP文本处理之中文汉字字符串转换为数组
  13. 基于物理的渲染PBR(一):pbr的基础理论和推导
  14. 【Vue element-admin 如何给侧边栏添加 Badge 计数标记 】
  15. 多官能度可聚会型光引发剂(图文说明)
  16. 贝壳找房 OLAP 平台实践
  17. 《Adobe Fireworks CS5中文版经典教程》——1.6 撤销操作
  18. python双样本t检验_SPSS详细操作 两个样本均数比较的t检验
  19. Frontend 当前前端的三种渲染方式
  20. POP和PUSH指令

热门文章

  1. 基于HTML大学生抗疫感动专题网页项目的设计与实现
  2. HE3050C锂电池保护IC,SOT23-3封装
  3. 使用pdf.js在web页面展示pdf文件
  4. 在项目管理中,如何避免出现低级错误?| 每天成就更大成功
  5. JustAuth于2019年7月21日正式喜提码云【GVP 】称号!
  6. 车联网Apollo(阿波罗),研究carlife车机端集成及开发,(WeLink,carplay/carlife)
  7. Meta(其他信息)
  8. 【操作教程】EasyNVR平台如何接入硬盘录像机?
  9. 【报告分享】2021美妆市场明星营销观察报告-CBNData(附下载)
  10. 咔咔截屏录屏大师如何录制手机视频