在上一篇文中介紹了Zygote程序的啟動過程,我們知道,Zygote程序是Android Java世界的開創者,所有的Java應用程式程序都由Zygote程序建立。Zygote建立應用程式程序過程其實就是複制自身程序位址空間作為應用程式程序的位址空間,是以在Zygote程序中加載的類和資源都可以共享給所有由Zygote程序孵化的應用程式,應用程式程序隻需加載自身私有資源就可以正常運作,Zygote程序是所有Android Java應用程式程序的父程序,Zygote程序和普通應用程式程序之間的關系正是面向對象程式設計語言中的繼承關系,應用程式程序繼承Zygote程序的所有資源,Zygote程序在啟動時加載所有應用程式程序運作所需的公共資源,即應用程式運作的共性資源;由于普通應用程式有自己的特性資源,是以普通應用程式在啟動時,隻需要加載自身特性資源就可以了。Linux程序間這種繼承關系加快了普通應用程式啟動的速度,也簡化了應用程式程序的建立過程。既然所有Java應用程式程序都是由Zygote程序建立,那麼Android系統是如何請求Zygote程序建立一個新的應用程式程序的呢?在Zygote程序啟動過程的源代碼分析中,我們介紹了Zygote程序在啟動過程中,會根據啟動參數建立第一Java程序,它就是SystemServer程序,它是Android系統至關重要的程序,運作中Android系統的絕大部分服務。普通應用程式程序是無法直接請求Zygote程序孵化新程序的,所有的程序建立請求都是由SystemServer程序發出的。本文依據源碼,詳細分析SystemServer程序的啟動過程。在Zygote程序進入循環監聽Socket模式前,會根據Zygote啟動參數來選擇是否啟動SystemServer程序,而Zygote程序的啟動是在Android的啟動腳本init.rc檔案中配置的:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
由于配置了參數--start-system-server,是以SystemServer程序會伴随Zygote程序的啟動而啟動: frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
if (argv[1].equals("start-system-server")) {
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
SystemServer雖然也是又Zygote程序孵化出來,但和普通的應用程式程序的啟動方式有所不同,這裡是通過調用startSystemServer()函數來啟動SystemServer程序的。 frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
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);
/* 請求fork SystemServer程序*/
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* pid為0表示子程序,即SystemServer程序,從此SystemServer程序與Zygote程序分道揚镳*/
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
在該函數中首先根據SystemServer程序啟動參數args構造一個Arguments對象,然後調用forkSystemServer()函數建立SystemServer程序,最後調用函數handleSystemServerProcess()啟動SystemServer程序,SystemServer啟動參數如下:
"--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",
參數解析
frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
Arguments(String args[]) throws IllegalArgumentException {
parseArgs(args);
}
在Arguments構造函數中直接調用parseArgs函數來解析SystemServer啟動參數
private void parseArgs(String args[])
throws IllegalArgumentException {
int curArg = 0;
for ( /* curArg */ ; curArg < args.length; curArg++) {
String arg = args[curArg];
if (arg.equals("--")) {
curArg++;
break;
} else if (arg.startsWith("--setuid=")) {
if (uidSpecified) {
throw new IllegalArgumentException("Duplicate arg specified");
}
uidSpecified = true;
//解析setuid參數,将程序uid儲存到變量uid中
uid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1));
} else if (arg.startsWith("--setgid=")) {
if (gidSpecified) {
throw new IllegalArgumentException("Duplicate arg specified");
}
gidSpecified = true;
//解析setgid參數,将程序gid儲存到變量gid中
gid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1));
} else if (arg.startsWith("--target-sdk-version=")) {
if (targetSdkVersionSpecified) {
throw new IllegalArgumentException("Duplicate target-sdk-version specified");
}
targetSdkVersionSpecified = true;
targetSdkVersion = Integer.parseInt(arg.substring(arg.indexOf('=') + 1));
//根據參數設定debugFlags标志位
} else if (arg.equals("--enable-debugger")) {
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
} else if (arg.equals("--enable-safemode")) {
debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
} else if (arg.equals("--enable-checkjni")) {
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
} else if (arg.equals("--enable-jni-logging")) {
debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
} else if (arg.equals("--enable-assert")) {
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
} else if (arg.equals("--peer-wait")) {
peerWait = true;
} else if (arg.equals("--runtime-init")) {
runtimeInit = true;
} else if (arg.startsWith("--capabilities=")) {
if (capabilitiesSpecified) {
throw new IllegalArgumentException("Duplicate arg specified");
}
capabilitiesSpecified = true;
String capString = arg.substring(arg.indexOf('=')+1);
String[] capStrings = capString.split(",", 2);
if (capStrings.length == 1) {
effectiveCapabilities = Long.decode(capStrings[0]);
permittedCapabilities = effectiveCapabilities;
} else {
permittedCapabilities = Long.decode(capStrings[0]);
effectiveCapabilities = Long.decode(capStrings[1]);
}
} else if (arg.startsWith("--rlimit=")) {
// Duplicate --rlimit arguments are specifically allowed.
String[] limitStrings= arg.substring(arg.indexOf('=')+1).split(",");
if (limitStrings.length != 3) {
throw new IllegalArgumentException("--rlimit= should have 3 comma-delimited ints");
}
int[] rlimitTuple = new int[limitStrings.length];
for(int i=0; i < limitStrings.length; i++) {
rlimitTuple[i] = Integer.parseInt(limitStrings[i]);
}
if (rlimits == null) {
rlimits = new ArrayList();
}
rlimits.add(rlimitTuple);
} else if (arg.equals("-classpath")) {
if (classpath != null) {
throw new IllegalArgumentException("Duplicate arg specified");
}
try {
classpath = args[++curArg];
} catch (IndexOutOfBoundsException ex) {
throw new IllegalArgumentException("-classpath requires argument");
}
} else if (arg.startsWith("--setgroups=")) {
if (gids != null) {
throw new IllegalArgumentException("Duplicate arg specified");
}
String[] params = arg.substring(arg.indexOf('=') + 1).split(",");
gids = new int[params.length];
for (int i = params.length - 1; i >= 0 ; i--) {
gids[i] = Integer.parseInt(params[i]);
}
} else if (arg.equals("--invoke-with")) {
if (invokeWith != null) {
throw new IllegalArgumentException("Duplicate arg specified");
}
try {
invokeWith = args[++curArg];
} catch (IndexOutOfBoundsException ex) {
throw new IllegalArgumentException("--invoke-with requires argument");
}
} else if (arg.startsWith("--nice-name=")) {
if (niceName != null) {
throw new IllegalArgumentException("Duplicate arg specified");
}
niceName = arg.substring(arg.indexOf('=') + 1);
} else {
break;
}
}
//參數-classpath 和 --runtime-init 不能同時設定
if (runtimeInit && classpath != null) {
throw new IllegalArgumentException("--runtime-init and -classpath are incompatible");
}
//儲存剩餘參數
remainingArgs = new String[args.length - curArg];
System.arraycopy(args, curArg, remainingArgs, 0,remainingArgs.length);
}
屬性配置
frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
public static void applyDebuggerSystemProperty(Arguments args) {
if ("1".equals(SystemProperties.get("ro.debuggable"))) {
args.debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
}
}
public static void applyInvokeWithSystemProperty(Arguments args) {
if (args.invokeWith == null && args.niceName != null) { //true
if (args.niceName != null) {
String property = "wrap." + args.niceName; //wrap.system_server
if (property.length() > 31) {
property = property.substring(0, 31);
}
args.invokeWith = SystemProperties.get(property);
if (args.invokeWith != null && args.invokeWith.length() == 0) {
args.invokeWith = null;
}
}
}
}
建立SystemServer程序
通過調用forkSystemServer函數來建立SystemServer程序
public static int forkSystemServer(int uid, int gid, int[] gids,
int debugFlags, int[][] rlimits,
long permittedCapabilities, long effectiveCapabilities) {
//停止Zygote程序中的其他線程,保證單線程
preFork();
int pid = nativeForkSystemServer(uid, gid, gids, debugFlags, rlimits,permittedCapabilities,effectiveCapabilities);
//啟動垃圾回收背景線程
postFork();
return pid;
}
該函數調用native函數nativeForkAndSpecialize來fork出systemserver程序
native public static int nativeForkSystemServer(int uid, int gid,int[] gids, int debugFlags, int[][] rlimits,
long permittedCapabilities, long effectiveCapabilities);
{ "nativeForkSystemServer", "(II[II[[IJJ)I", Dalvik_dalvik_system_Zygote_forkSystemServer },
根據JNI函數映射關系,最終會調用C++的Dalvik_dalvik_system_Zygote_forkSystemServer函數,在dalvik_system_Zygote.c檔案中實作:
static void Dalvik_dalvik_system_Zygote_forkSystemServer(const u4* args, JValue* pResult)
{
pid_t pid;
//根據參數,fork一個子程序
pid = forkAndSpecializeCommon(args, true);
/* The zygote process checks whether the child process has died or not. */
if (pid > 0) {
int status;
ALOGI("System server process %d has been created", pid);
gDvm.systemServerPid = 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.
*/
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
/*kill(getpid(), SIGKILL);*/
sleep(15);
//如果SystemServer程序退出,zygote将殺死自身程序
#ifdef HOST_DALVIK
reboot(RB_AUTOBOOT);
#else
android_reboot(ANDROID_RB_RESTART2, 0, (char *)"special-systemserver-died");
#endif
}
}
RETURN_INT(pid);
}
真正建立程序的核心函數:
static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
..........
pid = fork(); //使用Linux 系統調用fork來建立程序
if (pid == 0) {
//設定子程序的uid,gid等參數
} else if (pid > 0) {
/* the parent process */
}
return pid;
}
建立好SystemServer程序後,繼續調用preFork()來啟動背景線程
private static void postFork() {
Daemons.start(); //啟動背景線程
}
libcore\luni\src\main\java\java\lang\Daemons.java
public static void start() {
//啟動ReferenceQueueDaemon線程
ReferenceQueueDaemon.INSTANCE.start();
//啟動FinalizerDaemon線程
FinalizerDaemon.INSTANCE.start();
//啟動FinalizerWatchdogDaemon線程
FinalizerWatchdogDaemon.INSTANCE.start();
}
運作SystemServer程序
新建立的SystemServer程序會執行handleSystemServerProcess函數,來完成自己的使命。
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
//因為SystemServer是從Zygote程序中複制過來的,所有需要關閉從zygote繼承下來的socket
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 {
//傳遞剩餘參數給SystemServer并調用zygoteInit函數
// "--nice-name=system_server com.android.server.SystemServer"
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
}
由于由Zygote程序建立的子程序都會繼承Zygote程序在前面建立的Socket檔案描述符,而這裡的SystemServer程序又不會用到它,是以,這裡就調用closeServerSocket函數來關閉它。這個函數接着調用RuntimeInit.zygoteInit函數來進一步執行啟動SystemServer
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
//重定向Log輸出流
redirectLogStreams();
//初始化運作環境
commonInit();
//啟動Binder線程池
nativeZygoteInit();
//調用程式入口函數
applicationInit(targetSdkVersion, argv);
}
1. 初始化Log輸出流
/**
* Redirect System.out and System.err to the Android log.
*/
public static void redirectLogStreams() {
System.out.close();
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
System.err.close();
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
}
2.初始化運作環境
private static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
/* set default handler; this applies to all threads in the VM */
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
/*
* Install a TimezoneGetter subclass for ZoneInfo.db
*/
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();
new AndroidConfig();
/*
* Sets the default HTTP User-Agent used by HttpURLConnection.
*/
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
/*
* Wire socket tagging to traffic stats.
*/
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;
}
3.啟動Binder線程池
frameworks\base\core\jni\AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
frameworks\base\cmds\app_process\App_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
關于Binder線程池的啟動過程請參考 Android應用程式啟動Binder線程源碼分析
4.調用程序入口函數
static void invokeStaticMain(ClassLoader loader,
String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
//加載"com.android.server.SystemServer"類
Class<?> cl;
try {
cl = loader.loadClass(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException("Missing class when invoking static main " + className,
ex);
}
//通過類反射機制查找SystemServer類中的main函數
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);
}
//擷取main函數的修飾符
int modifiers = m.getModifiers();
//程序入口函數必須為靜态Public類型
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.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
抛出MethodAndArgsCaller異常,并在ZygoteInit.main()函數中捕獲該異常,這樣就可以清除應用程式程序建立過程的調用棧,将應用程式啟動的入口函數設定為SystemServer.main() frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) {
try {
...
//捕獲MethodAndArgsCaller異常
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
在該函數裡,捕獲了MethodAndArgsCaller異常,并調用MethodAndArgsCaller類的run()方法來處理異常
public static class MethodAndArgsCaller extends Exception implements Runnable {
public void run() {
try {
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函數 frameworks\base\services\java\com\android\server\SystemServer.java
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);
}
//啟動SamplingProfilerIntegration線程,并且每隔1小時寫一次快照
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);
//加載libandroid_servers.so庫
System.loadLibrary("android_servers");
//進入服務啟動第一階段:啟動native服務
init1(args);
}
SystemServer類的main函數是SystemServer程序的入口函數,在該函數裡,首先加載libandroid_servers.so庫,然後調用init1啟動native相關服務 frameworks\base\services\jni\com_android_server_SystemServer.cpp
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
system_init();
}
frameworks\base\cmds\system_server\library\system_init.cpp
extern "C" status_t system_init()
{
ALOGI("Entered system_init()");
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("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.
ALOGI("System server: starting Android runtime.\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
ALOGI("System server: starting Android services.\n");
JNIEnv* env = runtime->getJNIEnv();
if (env == NULL) {
return UNKNOWN_ERROR;
}
//通過JNI調用SystemServer類的init2()函數,啟動Java服務
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);
//啟動Binder線程池
ALOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
ALOGI("System server: exiting thread pool.\n");
return NO_ERROR;
}
在該函數裡,通過JNI調用SystemServer類中的init2函數進一步啟動Android系統中的Java服務,然後将SystemServer程序的主線程注冊到Binder線程池中 frameworks\base\services\java\com\android\server\SystemServer.java
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
//通過啟動ServerThread線程來啟動Java服務
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
這裡通過啟動一個名為android.server.ServerThread的線程來啟動Android系統服務 frameworks\base\services\java\com\android\server\SystemServer$ServerThread
public void run() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,SystemClock.uptimeMillis());
Looper.prepare();
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
BinderInternal.disableBackgroundScheduling(true);
android.os.Process.setCanSelfBackground(false);
....
ServiceManager.addService("entropy", new EntropyMixer());
ServiceManager.addService(Context.POWER_SERVICE, power);
ServiceManager.addService("security", security);
ServiceManager.addService("telephony.registry",new TelephonyRegistry(context, 0));
ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE,new SchedulingPolicyService());
....
//PowerManagerServer WakeLock dump thread
(new Thread(new WakelockMonitor(power))).start();
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
Looper.loop();
Slog.d(TAG, "System ServerThread is exiting!");
}
在run函數中啟動并注冊Java中的各種Service。至此SystemServer程序啟動過程分析完畢!啟動過程式列圖如下所示: