Copyright:http://blog.youkuaiyun.com/myzhzygh/article/details/7721857
1.Introduction
在文档“Android boot and init”中我们已经研究了Android系统的引导和加载过程。本章描述了在Kernel启动完成之后,Android系统执行了根文件系统目录下的init脚本,通过init脚本建立Android系统最初运行的环境。可以看出在这篇文章中,我们更多的侧重于内核启动和init脚本所完成的功能。而在本文中,我们将更多的讨论系统init脚本执行完之后,Android系统是如何完成后续启动过程,包括虚拟机创建,系统服务加载,系统应用程序启动等内容。
Android系统是基于Linux kernel的,抛开Linux kernel启动的过程,从另一个角度,我们可以认为Android的启动过程是从进程init开始的,也就是init脚本执行完成之后第一个执行的程序,所以它是后续所有进程的祖先进程。
2.Native System Service
如果说init程序之前的操作是在为Android系统的启动做准备工作,那么从Android系统的init程序开始,我们就是在真正的创建Android系统运行的环境。在这个过程中,我们要完成文件系统节点的创建,设置系统环境变量和启动相应的系统服务等操作。Android系统提供了灵活的init.rc配置文件,能够实现对这个阶段系统操作进行灵活的配置。在每次系统启动的时候,init程序都会对init.rc配置文件进行解析,完成系统基本参数设置和基本服务的加载。下面我们看看在init.rc文件中所描述的的服务。
init.rc 文件里面的服务有2种, class core和class main。对 init.rc文件中描述的 service 按照 class <name>分类如下:
class core:
service ueventd /sbin/ueventd
service console /system/bin/sh
service adbd /sbin/adbd
service servicemanager /system/bin/servicemanager
service vold /system/bin/vold
class main:
service netd /system/bin/netd
service debuggerd /system/bin/debuggerd
service ril-daemon /system/bin/rild
service surfaceflinger /system/bin/surfaceflinger
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
service drm /system/bin/drmserver
service media /system/bin/mediaserver
service bootanim /system/bin/bootanimation
service dbus /system/bin/dbus-daemon --system --nofork
service bluetoothd /system/bin/bluetoothd -n
service installd /system/bin/installd
service flash_recovery /system/etc/install-recovery.sh
service racoon /system/bin/racoon
service mtpd /system/bin/mtpd
service keystore /system/bin/keystore /data/misc/keystore
service dumpstate /system/bin/dumpstate -s
上面列出了init.rc中描述的所有服务,针对具体的vendor,这些服务并不是都需要启动。在 class core服务启动以后, class main开始启动。下面列出针对Service的一些Options。
表1:init.rc service options
Options for Service | Description |
setenv <name> <value> | 在启动服务时设置环境变量 |
user <username> | 运行服务之前切换用户 |
oneshot | 如果服务已经存在,将不再启动 |
class <classname> | 为服务设置名字,具有相同名字的服务将一起启动或者关闭 |
socket <name> <type> <perm> [ <user> [ <group> ] ] | 创建以<name>命名的 socket,并将该 socket的文件描述符返回给启动的服务 |
onrestart <command> | 在服务重新启动的时候执行<command> |
对于init程序及init.rc其它规则我们在这里不再做详细的描述。具体可参考Android init language Spec。
3.Zygote Service
下面我们将研究Android系统最重要的服务zygote的启动流程。首先我们必须清楚zygote服务在init.rc配置文件中的描述形式:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
Zygote服务是标志进入 android系统的最重要服务之一,从上面的描述可以看到,服务名字为 zygote,实际的执行体是 ‘/system/bin/app_process’程序;同时zygote服务带有--zygote和--start-system-server参数,这些参数对zygote服务的启动具有非常重要的作用。zygote服务相关选项所表示的含义如表1所示:
表2:zygote service sample
Option | Description |
class main | 说明service zygote属于main类型的service |
socket zygote stream 666 | 在服务启动之前,需要创建一个命名为zygote的socket,该socket访问权限标示为666. |
onrestart write /sys/android_power/request_state wake | 该服务重启的时候,需要向电源管理中写入wake参数,电源管理请求为wake |
onrestart restart media | 该服务重启的时候,需要重新启动media服务 |
onrestart restart netd | 该服务重启的时候,需要重新启动netd服务 |
从本文之前的内容我们知道,zygote服务只是init程序在系统启动阶段启动的服务之一,具体的说是main类型服务成员之一。但由于Android系统作为特殊的Linux系统,它所有应用程序都是运行在Java语言的基础上,所以为了支持这种特性,Android系统就必须构建支持Java程序运行的Runtime环境。而Zygote服务就是构建Java Runtime环境的起点,换句话说它是所有Java程序的始祖。所以我们有必要详细的研究,最终清楚Android Runtime构建的流程,并了解在这个过程中所进行的其它操作,如2D display环境的初始化等。
Zygote服务的执行实体为 ’/system/bin/app_process’,所以我们以app_process程序为研究的入口点,具体是以app_process程序的main方法为入口点,通过对main方法的代码实现进行宏观的分析,从分析的结果我们得出其实现的主要逻辑功能如下:
1. 构造AndroidRuntime类的实例
AppRuntime runtime;
系统的AndroidRuntime类定义了基本的Android Runtime接口,但AndroidRuntime类作为一个抽象类,不能实例化自己的对象。在app_process程序中定义了AppRuntime类, AppRuntime类作为AndroidRuntime类的派生类,继承了AndroidRuntime类的部分接口实现,同时实现了AndroidRuntime类所定义的抽象接口,所以zygote服务的启动,我们首先实例化了一个AppRuntime类的对象,作为Runtime实例。接下来我们分析AppRuntime类和AndroidRuntime类的构造函数,从AppRuntime类的构造函数实现我们知道AppRuntime类在构造函数并没有做什么事,所以我们重点研究了AndroidRuntime类的构造函数。
AndroidRuntime::AndroidRuntime()
{
SkGraphics::Init();
// this sets our preference for 16bit images during decode
// in case the src is opaque and 24bit
SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
// This cache is shared between browser native images, and java "purgeable"
// bitmaps. This globalpool is for images that do not either use the java
// heap, or are not backed by ashmem. See BitmapFactory.cpp for the key
// java call site.
SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);
// There is also a global font cache, but its budget is specified in code
// see SkFontHost_android.cpp
// Pre-allocate enough space to hold a fair number of options.
mOptions.setCapacity(20);
assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}
从上面AndroidRuntime类的构造函数实现来看,构造函数最重要的任务就是初始化负责系统2D Display的Skia库,指定系统默认颜色格式,设置images共享缓冲区的大小。
SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);
2. 解析init.rc中zygote传递的启动参数,设置Runtime启动参数
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
className = arg;
break;
}
}
3. 解析Runtime启动参数,启动Runtime
runtime.start("com.android.internal.os.ZygoteInit", "start-system-server");
在完成Android Runtime对象构造,zygote服务的参数解析之后,系统将调用AndroidRuntime对象的start方法开始建立Java Runtime环境。根据zygote服务的定义, Android Runtime的类型为StartMode::Zygote,start方法接收的参数分别为"com.android.internal.os.ZygoteInit"和"start-system-server"。下面是start方法的代码实现,用红色斜体标示的区域是我们重点研究的部分:
void AndroidRuntime::start(const char* className, const char* options)
{
LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)")
...
/* start the virtual machine */
//设置 dalvik虚拟机参数,创建并启动虚拟机 JNIEnv* env;
①if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\n");
return;
}
...
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
//将类名 com.xxx.xxx转换成 com/xxx/xxx
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// jni调用 java方法,获取对应类名的 class,然后调用静态 main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
LOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
②env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
free(slashClassName);
//销毁Java VM
LOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly\n");
}
通过分析AndroidRuntime类的start方法实现,start方法实现的逻辑功能主要包含两个部分:创建Android Dalvik VM;执行Android Java 程序,包括启动Java层系统核心服务和系统核心应用程序。
①创建Android Dalvik VM:调用startVm方法创建Dalvik VM,并构建JNI Environment;随后调用startReg方法向Runtime注册系统的所有JNI Native Methods。
②执行Android Java程序:调用执行参数className类的main方法。根据传递的参数,最终执行的是"com.android.internal.os.ZygoteInit"类的main方法。
通过对zygote服务启动的分析,我用图1给出了zygote服务启动的整体流程,以及应用程序启动的框架。同时我们通过图2给出了启动过程中各阶段所处的进程空间。接下来我们将结合图1和图2对start函数的逻辑功能进行详细的分析。
com/android/os/ZygoteInit作为Runtime的参数,在Java运行环境建立好之后,ZygoteInit是系统运行的第一个Java程序,Runtime调用了ZygoteInit类的main方法,在main方法中,由于app_process启动的时候是带有—start-system-server参数的,在这个时候系统调用了starServerSystem方法,在该方法中,fork一个子进程来处理SystemServer启动请求,在子进程中首先调用RuntimeInit类的zygoteInit方法。
4.Creating Android Dalvik VM
从图2我们可以看到,在app_process创建AndroidRuntime的实例之后,就会调用start方法。start方法首要任务就是创建Android Dalvik VM。
创建Android Dalvik VM主要包含三个方面:创建JavaVM,构建JNI Environment,注册Android系统Native JNI Method。
创建JavaVM和构建JNI Environment就是分别实现JNIInvokeInterface接口和JNINativeInterface接口中的函数,然后用实现的接口实例初始化JavaVMExt类和JNIEnvExt类中相应的接口指针,完成JavaVM和JNI Environment的创建。一个AndroidRuntime包含一个JavaVM实例,一个JavaVM实例理论上可以包含多个JNIEnv实例,但通常一个JavaVM实例只有一个JNIEnv实例,Dalvik也不例外。
在完成JavaVM和JNI Enviroment创建之后,为了使虚拟机支持Android系统Java程序的运行,还必须注册Android系统的所有Native JNI Method。所谓Android系统的Native JNI Method,就是Android系统中所有JNI库中实现的导出方法,通过这些方法,Native层向Java Framework层提供服务,支撑整个Android Java Framework层。到此,整个Dalvik VM已创建完成。
5.Booting Android Java Program
Start方法完成Android Dalvik VM创建之后,接下来任务就是执行参数指示的Java程序。根据start方法接收的参数,我们将在本地层调用执行ZygoteInit类的main方法,这也是zygote服务启动过程中第一次由本地层调用Java层的方法。一定程度上,从此zygote服务将进入以JAVA程序为主导的运行阶段。接下来我们将从ZygoteInit类的main方法开始分析。值得注意的是,到目前为止我们仍处于zygote服务进程空间,也就是图2中绿色标示的区域。下面是ZygoteInit类的main方法实现代码:
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
①registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//预加载资源,有 preloadClasses()和 preloadResources(),加载的开始和结束会被记录在 /system/etc/event-log-tags文件中
②preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
gc();
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
③if (argv[1].equals("start-system-server")) {
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
④if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
接下来我们将对"com.android.internal.os.ZygoteInit"类的main方法中红色标示的的区域按序号顺序进行分析:
①调用registerZygoteSocket方法注册socket server。按照init.rc中的描述,在启动zygote服务之前,我们先创建了一个命名为zygote的socket,在zygote socket创建成功之后,会将创建zygote socket的文件描述符存放在ANDROID_SOCKET_zygote环境变量中。这里实际上是将zygote服务与zygote socket进行绑定,是zygote服务作为zygote socket的服务端;
②调用preload预加载系统的类库和资源。这样其他程序启动将不再加载系统资源,只需加载自己程序的资源,这样就达到系统资源在程序之间共享;
③对main参数进行判断,是否有"start-system-server"选项存在。在调用 ZygoteInit的 main 函数时,已经传入 start-system-server,接下来将调用startSystemServer方法。如下是startSystemServer的代码实现:
private static boolean startSystemServer()
throws 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,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
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);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
startSystemServer的目的就是通过调用Zygote类的forkSystemServer方法在zygote服务主进程中派生一个命名为“system_server”的子进程,如图2中黄色标示的区域。从startSystemServer的代码中我们可以看到在system_server子进程创建成功之后,在system_server进程空间中会调用handleSystemServerProcess方法。
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();
// set umask to 0077 so new files and directories will default to owner-only permissions.
FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, parsedArgs.remainingArgs);
} else {
/*
* Pass the remaining arguments to SystemServer.
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
/* should never reach here */
}
handleSystemServerProcess方法中首先调用closeServerSocket()关闭zygote socket。 system_server作为zygote服务派生的子进程,继承了父进程的所有资源,包括它打开的文件描述符,因为zygote主进程之前注册了zygote socket,所以system_server子进程也继承了zygote socket资源,但在system_server子进程中并不需要对zygote socket进行监听,所以zygote socket对于system_server子进程并没有什么用途,需要将zygote socket关闭。在这里关闭zygote socket并不是必须的,也不影响system_server子进程,但从ZygoteInit类的main方法角度出发,在这里关闭zygote socket是有必要的,如果在这里不关闭zygote socket,当在子进程中发生RuntimeException时,会有可能产生死锁。
最后调用RuntimeInit.zygoteInit的方法,然后由该方法调用com.android.server.SystemServer类的main方法,但事实并非这样,而只是仅仅抛出了一个MethodAndArgsCaller异常。调用SystemServer类main方法的动作最后交给ZygoteInit的catch模块来执行。为什么这样,只是因为system_server派生于zygote进程,继承了zygote的所有资源,包括代码,但在system_server进程中要避免执行try模块中后续的代码,所以通过异常的方式跳过try模块中后续代码,这里是通过异常的方式控制代码的执行流程,是对异常的一种特殊应用。
SystemServer类的mail方法,完成系统的初始化,初始化的过程分为两步init1和init2,如图3所示。
如下是SystemServer类mail方法的代码实现:
public class SystemServer {
……
native public static void init1(String[] args);
public static void main(String[] args) {
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
// 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.
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// Mmmmmm... more memory!
dalvik.system.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.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
System.loadLibrary("android_servers");
init1(args);
}
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
}
首先调用init1,完成本地服务的初始化。该方法的Native JNI实现位于libandroid_servers库中,该库通过调用了本地libsystem_server库中的system_init方法实现。在该方法中以线程的形式启动本地Service,例如SensorService线程等,SurfaceFlinger也可以以线程的形式启动。
extern "C" status_t system_init()
{
LOGI("Entered system_init()");
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p\n", sm.get());
sp<GrimReaper> grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service
SensorService::instantiate();
}
// And now start the Android runtime. We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
LOGI("System server: starting Android runtime.\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
LOGI("System server: starting Android services.\n");
JNIEnv* env = runtime->getJNIEnv();
if (env == NULL) {
return UNKNOWN_ERROR;
}
jclass clazz = env->FindClass("com/android/server/SystemServer");
if (clazz == NULL) {
return UNKNOWN_ERROR;
}
jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
if (methodId == NULL) {
return UNKNOWN_ERROR;
}
env->CallStaticVoidMethod(clazz, methodId);
LOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting thread pool.\n");
return NO_ERROR;
}
根据系统参数,Init1完成本地Service线程的启动之后,在init1方法中会回调Java层的init2方法,启动支持Android Java程序运行的所有上层服务。
在init2方法中,在ServerThread线程中启动Android Java层的所有核心服务,每个核心服务以线程的方式为系统提供服务。
启动的所有核心服务见文档Android frameworks service.doc(Steven Fu)
ActivityManagerService是system_server进程启动的最重要的服务之一,在ActivityManagerService服务的支持下,我们可以启动系统的应用程序。
如果说system_server是Android启动的第一个Java进程,那么systemUI是系统启动的第二个Java进程。从前面分析我们知道,system_server进程的创建是zygote service派生的。而systemUI进程的的创建与system_server的创建有很大的不同。它的创建过程代表了Android系统中一般Java程序的创建过程。下面是system_server中启动systemUI进程的实现:
static final void startSystemUi(Context context) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
Slog.d(TAG, "Starting service: " + intent);
context.startService(intent);
}
ActivityManagerService.self().systemReady(new Runnable() {
public void run() {
Slog.i(TAG, "Making services ready");
startSystemUi(contextF);
try {
if (batteryF != null) batteryF.systemReady();
} catch (Throwable e) {
reportWtf("making Battery Service ready", e);
}
try {
if (networkManagementF != null) networkManagementF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
}
try {
if (networkStatsF != null) networkStatsF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Stats Service ready", e);
}
try {
if (networkPolicyF != null) networkPolicyF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Policy Service ready", e);
}
try {
if (connectivityF != null) connectivityF.systemReady();
} catch (Throwable e) {
reportWtf("making Connectivity Service ready", e);
}
try {
if (dockF != null) dockF.systemReady();
} catch (Throwable e) {
reportWtf("making Dock Service ready", e);
}
try {
if (usbF != null) usbF.systemReady();
} catch (Throwable e) {
reportWtf("making USB Service ready", e);
}
try {
if (uiModeF != null) uiModeF.systemReady();
} catch (Throwable e) {
reportWtf("making UI Mode Service ready", e);
}
try {
if (recognitionF != null) recognitionF.systemReady();
} catch (Throwable e) {
reportWtf("making Recognition Service ready", e);
}
Watchdog.getInstance().start();
// It is now okay to let the various system services start their
// third party code...
try {
if (appWidgetF != null) appWidgetF.systemReady(safeMode);
} catch (Throwable e) {
reportWtf("making App Widget Service ready", e);
}
try {
if (wallpaperF != null) wallpaperF.systemReady();
} catch (Throwable e) {
reportWtf("making Wallpaper Service ready", e);
}
try {
if (immF != null) immF.systemReady(statusBarF);
} catch (Throwable e) {
reportWtf("making Input Method Service ready", e);
}
try {
if (locationF != null) locationF.systemReady();
} catch (Throwable e) {
reportWtf("making Location Service ready", e);
}
try {
if (countryDetectorF != null) countryDetectorF.systemReady();
} catch (Throwable e) {
reportWtf("making Country Detector Service ready", e);
}
try {
if (throttleF != null) throttleF.systemReady();
} catch (Throwable e) {
reportWtf("making Throttle Service ready", e);
}
try {
if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Time Service ready", e);
}
try {
if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady();
} catch (Throwable e) {
reportWtf("making Text Services Manager Service ready", e);
}
}
});
通过对上的代码进行分析,systemUI进程的创建过程如图4所示:
在ServerThread线程最后,通过ActivityManagerService的SystemReady方法启动systemUI进程。通过在SystemReady Runable 接口的Run方法中调用ActivityManagerService类的startService方法启动systemUI进程。在startService方法中会调用startProcessLocked方法,该方法会调用Process类的start方法创建新的进程。ActivityManagerService通过向之前注册的zygote socket发送创建进程请求。当zygote服务接收到请求之后,会fork新的子进程实例,并返回给ActivityManagerService,最终完成systemUI进程的创建。
/**
* Start a new process.
*
* <p>If processes are enabled, a new process is created and the
* static main() function of a <var>processClass</var> is executed there.
* The process will continue running after this function returns.
*
* <p>If processes are not enabled, a new thread in the caller's
* process is created and main() of <var>processClass</var> called there.
*
* <p>The niceName parameter, if not an empty string, is a custom name to
* give to the process instead of using processClass. This allows you to
* make easily identifyable processes even if you are using the same base
* <var>processClass</var> to start them.
*
* @param processClass The class to use as the process's main entry
* point.
* @param niceName A more readable name to use for the process.
* @param uid The user-id under which the process will run.
* @param gid The group-id under which the process will run.
* @param gids Additional group-ids associated with the process.
* @param debugFlags Additional flags.
* @param targetSdkVersion The target SDK version for the app.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
* @return An object that describes the result of the attempt to start the process.
* @throws RuntimeException on fatal start failure
*
* {@hide}
*/
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int targetSdkVersion,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, targetSdkVersion, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int targetSdkVersion,
String[] extraArgs)
throws ZygoteStartFailedEx {
argsForZygote.add("--runtime-init");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
……
return zygoteSendArgsAndGetResult(argsForZygote);
}
同样在ActivityManagerService的SystemReady方法最后会调用resumeTopActivityLocked(Launcher, home)方法启动Launcher进程。HOME启动以后,ActivityManagerService中 finishBooting 方法会发出 Intent.ACTION_BOOT_COMPLETED广播,随后系统会启动其它的Java程序。
调用resumeTopActivityLocked方法的地方有很多,resume activity的时候或者出错的时候,调用一次以后就不再调用。
系统其它Java程序的启动和systemUI的启动过程类似,不同的是,systemUI是在system_server进程空间内,直接调用ActivityManagerService Context的方法启动的;其它一般Java程序的启动一般是在Launcher环境下启动的,需要通过Android系统向应用程序层提供的接口间接获取ActivityManagerService提供的服务,而不是直接直接获取,最后通过ActivityManagerService Java层核心服务完成进程的创建。
④zygote和system_server进程序列。从startSystemServer开始我们分析了system_server子进程中进行的逻辑处理,system_server子进程为系统Java进程的创建提供了必要的支持。ZygoteInit类中ZYGOTE_FORK_MODE被赋值为false,所以在zygote启动的主进程中,在fork调用返回之后,主进程中将调用runSelectLoopMode,开始监听之前通过 registerZygoteSocket() 函数调用注册的 zygote socket连接。我们知道在system_server子进程中最终通过抛出 MethodAndArgsCaller异常,跳过try语句块中后续代码的执行,所以system_server子进程中不会执行runSelectLoopMode方法调用,最后在 catch语句块中调用 com.android.server.SystemServer类的main方法。main方法的执行过程在上文中已经描述。