Android系统从开机到Launcher启动的整体流程,其中包括Init进程,Zygote进程,SystemServer进程及Launcher的启动流程。
Android 系统启动流程
Android 启动流程大致分为以下几步
- 1.Init进程的启动。
- 2.Zygote进程的启动
- 3.SystemServer进程的启动
- 4.Launcher的启动
目录
Init进程的启动
Init进程为Android系统中第一个进程,进程号为1.内核启动之后,通过init.rc配置文件,启动init进程。init进程会进行初始化和启动属性服务,并且启动Zygote进程。
Zygote进程
Zygote进程,意为“孵化器”,我们的应用程序进程通过Zygote fork自身的方式来创建进程。同时SystemServer进程也是通过Zygote进程来fork创建的。Zygote进程中创建了Java虚拟机,并且为虚拟机注册了JNI方法。通过JNI方法进入ZygoteInit.java文件中的main(),由此进入了Java层。
core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) {
try {
......
String socketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
// 1 Zygote进程创建了一个Socket,用于之后的AMS请求连接。
zygoteServer.registerServerSocket(socketName);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog); // 2 Zygote预加载类和资源
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
......
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer); // 3 开启SystemServer进程
}
Log.i(TAG, "Accepting command socket connections");
zygoteServer.runSelectLoop(abiList); // 4 启动Socket连接,等待AMS请求。
zygoteServer.closeServerSocket();
} catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
}
}
在main()函数的注释1中,我们可以看到Zygote进程创建了一个Socket,这个Socket是用于之后AMS请求连接的,因为AMS在请求创建根Activity之前会先判断当前应用程序进程是否已经创建,如果未创建则会通过这个Socket请求Zygote进程来fork应用程序进程。也即Zygote进程和AMS所在进程(SystemServer进程)是通过Socket进行通信的。
在注释2中,Zygote进行预加载类和资源。
从注释3中可见,在预加载完类和资源之后,Zygote进程开始创建启动SystemServer进程。
而在注释4中可见,Zygote进程开始启动运行Socket连接,等待AMS请求。我们可以看下代码及注释是如何开启Socket等待AMS连接的。
core\java\com\android\internal\os\ZygoteServer.java
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* @throws Zygote.MethodAndArgsCaller in a child process when a main()
* should be executed.
*/
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
while (true) { // 无线循环来监听AMS的连接请求。
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce(this); // Zygote进程接收到AMS请求之后进行fork本身来创建应用程序进程。
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
所以从ZygoteInit的main()方法中我们可以知道Zygote进程中完成了以下几件事情:
- 创建了一个用于AMS请求连接的Socket。
- 预加载类和资源
- 创建启动SystemServer进程
- 开启Socket连接,等待AMS请求。
SystemServer进程的启动
从上文我们可以得知,SystemServer进程由Zygote进程创建并启动,函数入口为startSystemServer方法,我们可以来分析下这个方法。
core\java\com\android\internal\os\ZygoteInit.java
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
throws Zygote.MethodAndArgsCaller, RuntimeException {
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
// 将SystemServer进程启动参数,封装为Arguments类的一个对象依次传递下去。
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities); // Zygote进程通过fork自身来创建SystemServer进程。
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) { // 进程号为0,说明运行在子进程中。此处即为在SystemeServer进程中运行。
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 关闭Socket连接
zygoteServer.closeServerSocket();
handleSystemServerProcess(parsedArgs);
}
return true;
}
首先进行fork之前的准备工作,初始化参数args[],将其封装为ZygoteConnection.Arguments类的一个对象,之后依次传递下去。随后通过Zygote.forkSystemServer来fork本身来创建SystemServer进程。我们先看下在Zygote.java中是如何forkSystemServer的。
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 debugFlags bit flags that enable debugging 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. // 如果是子进程,pid返回0。如果是父进程,则返回-1。
*/
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
VM_HOOKS.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
// 通过native方法来创建SystemServer进程。
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true);
}
VM_HOOKS.postForkCommon();
return pid;
}
可以看到,forkSystemServer通过调用native方法nativeForkSystemServer来进行创建SystemServer进程的,同时可从函数的javadoc文档注释中看到,当fork SystemServer进程之后在SystemServer进程中将返回0。然后再回过头去看startSystemServer函数。
/* For child process */
if (pid == 0) { // 进程号为0,说明运行在子进程中。此处即为在SystemeServer进程中运行。
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 关闭Socket连接
zygoteServer.closeServerSocket();
handleSystemServerProcess(parsedArgs);
}
在Zygote进程fork SystemServer进程之后,在SystemServer进程中会首先关闭Socket连接,然后再处理一些SystemServer进程需要初始化的一些事情。这时有个问题来了,为什么在SystemServer进程中需要关闭Socket连接呢?因为SystemServer进程是通过Zygote进程fork本身创建的,而之前我们分析Zygote进程时知道,Zygote进行创建了Java虚拟机及用于等待AMS进程连接的Socket所以SystemServer进程也会拥有这些。而在SystemServer进程中不需要这个Socket,所以需要将其关闭。然后我们再来看下handleSystemServerProcess方法来了解SystemServer进程具体做了哪些事情。
core\java\com\android\internal\os\ZygoteInit.java
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws Zygote.MethodAndArgsCaller {
// ......
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
// ......
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);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
// 创建PathClassLoader。
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
// 传入剩下的参数给SystemServer进程。
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
从方法调用依次看来,我们知道参数parsedArgs是从startSystemServer函数中SystemServer启动参数args[]封装而来,而parsedArgs.invokeWith是为null的。所以进入下面的判断。在中文注释中可以看到,SystemServer进程创建了Android类加载器中的其中一类 : PathClassLoader。(Android中类加载器有,BootClassLoader, DexClassLoader, PathClassLoader)然后再看剩下的SystemServer启动参数传入SystemServer。进入到ZygoteInit.java的ZygoteInit.zygoteInit方法。
core\java\com\android\internal\os\ZygoteInit.java
/**
* 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> [--] <start class name> <args>
* </ul>
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
// 创建Binder线程池
ZygoteInit.nativeZygoteInit();
// 进行初始化操作
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
这里有两个重要的方法。ZygoteInit.nativeZygoteInit()和RuntimeInit.applicationInit()。第一个方法调用native方法创建了Binder线程池,为了SystemServer进程可以和其他进程进行通信。而第二个方法进行了初始化的操作。我们来看下RuntimeInit.java的applicationInit().
core\java\com\android\internal\os\RuntimeInit.java
protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
// ......
final Arguments args = new Arguments(argv);
//......
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
在applicationInit()中最主要调用了方法invokeStaticMain。
/**
* 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
*/
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
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);
}
// 下文的英文注释也说了,异常最终抛给ZygoteInit.main()来处理。并且这样的处理会清除设置过程中的堆栈帧。
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new Zygote.MethodAndArgsCaller(m, argv);
}
可以看到在invokeStaticMain()中通过className反射拿到要执行的类,而这里的className也就是com.android.server.SystemServer,拿到的类也就是SystemServer类。而这里的className为什么就是SystemServer类,具体可通过调用栈依次向前看,可以在ZygoteInit.java中的startSystemServer()方法中找到args这个字符串数组,最后一个字符串"com.android.server.SystemServer"就是我们这里的className。方法m为main方法。然后方法最终会抛出MethodAndArgsCaller异常。异常依次向上抛,最终在ZygoteInit.java的main()中处理,我们可以返回看下。
core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) {
//......
try {
zygoteServer.closeServerSocket();
} catch (Zygote.MethodAndArgsCaller caller) {
// 通过捕获抛出的异常来执行main方法
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
}
}
最终捕获异常来运行SystemServer中的main方法。为什么需要以这种方式来执行main方法呢,因为在启动SystemServer的过程中调用了一系列的准备方法,而通过抛异常的方式可以清除设置过程中的堆栈帧,让SystemServer看起来像从main入口处开始执行。这样SystemServer进程就开始执行main()函数了。
services\java\com\android\server\SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
执行SystemServer中的run()方法。
private void run() {
try {
// 创建Looper
Looper.prepareMainLooper();
// 加载so文件
// Initialize native services.
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();
// 创建了SystemServiceManager
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
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();
// 启动核心服务
startCoreServices();
// 启动其他服务
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
......
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
从run()的注释中我们可以知道,SystemServer创建了SystemServiceManager并且启动了三种服务。(Android把系统服务分为三种,分别为引导服务,核心服务,其他服务)。其中ActivityManagerService和PackageManagerService属于引导服务。在服务创建之后,SystemServiceManger会通过单例将服务添加进去,用来管理系统中的各种Service,用于系统的C/S架构中的Binder通信机制,某个Client需要使用服务时,需要先到SystemServiceManager中查询服务,然后通过Binder和Service所在的Server进程建立通信来调用服务。
所以SystemServer进程做了以下事情:
- 创建了Binder线程池,为了与其他进程进行通信。
- 创建SystemServiceManager启动并管理系统服务。
- 创建并启动三种系统服务。
Launcher的启动
Launcher的启动由AMS(ActivityManagerService)启动之后开始的,通过一系列的调用
`AMS(systemReady())-ActivityStackSupervisor(resumeFocusedStackTopActivityLocked())-ActivityStack(resumeTopActivityUncheckedLocked())-ActivityStack(resumeTopActivityInnerLocked())-ActivityStackSupervisor(resumeHomeStackTask)-AMS(startHomeActivityLocked())`
一系列的调用,最后调用AMS的startHomeActivityLocked()方法。
services\core\java\com\android\server\am\ActivityManagerService.java
boolean startHomeActivityLocked(int userId, String reason) {
......
// 创建Launcher需要的Intent
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
// For ANR debugging to verify if the user activity is the one that actually
// launched.
final String myReason = reason + ":" + userId + ":" + resolvedUserId;
// 启动Launcher
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
通过getHomeIntent()创建Launcher需要的Intent,然后startHomeActivityLocked()启动Launcher。
services\core\java\com\android\server\am\ActivityStarter.java
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(reason);
mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
if (mSupervisor.inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
mSupervisor.scheduleResumeTopActivities();
}
}
startHomeActivityLocked()通过startActivityLocked()启动,进入了Activity的启动流程,启动Launcher。
- 遗留问题:https://www.zhihu.com/question/345196352 (该问题已解答)