前言
在Android 系统启动流程(二) zygote启动流程这片文章中,我们学习了Zygote的启动过程,并且知道 Zygote创建并启动了SystemServer,这篇文章我们来学习下SystemServer的启动过程。
1 Zygote启动SystemServer
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
);
...
/* Hardcoded command line to start the system server */
//设置参数
String args[] = {
"--setuid=1000",//uid,pid的设置
"--setgid=1000",
/// M: [Wi-Fi Hotspot Manager] system_server add dhcp (1014) group to access
/// "/data/misc/dhcp/dnsmasq.leases"
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1014,1018,1021,1023," +
"1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",//进程名
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",//启动类
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);//将args封装成Arguments
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
//1 fork子进程,用于运行SystemServer
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.runtimeFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();//关闭从Zygote复制过来的Socket
return handleSystemServerProcess(parsedArgs);//2 完成system_server进程剩余的工作
}
return null;
}
在注释1处调用forkSystemServer来fork子进程,pid = 0说明进入子进程,然后在注释2处调用handleSystemServerProcess来完成system_server进程剩余的工作,我们来看下handleSystemServerProcess做了上面工作。
2 启动SystemServer
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);//设置进程名:system_server
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);//执行dex优化
// Capturing profiles is only supported for debug or eng builds since selinux normally
// prevents it.
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
try {
prepareSystemServerProfile(systemServerClasspath);
} catch (Exception e) {
Log.wtf(TAG, "Failed to set up system server profile", e);
}
}
}
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
// If we have a non-null system server class path, we'll have to duplicate the
// existing arguments and append the classpath to it. ART will handle the classpath
// correctly when we exec a new process.
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(args, 0, amendedArgs, 2, args.length);
args = amendedArgs;
}
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//1
}
/* should never reach here */
}
注释1处调用ZygoteInit的zygoteInit,下面来看下它干了什么。
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();//1
ZygoteInit.nativeZygoteInit();//2
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//3
}
- 注释1:通用初始化
- 注释2:Zygote初始化
- 注释3:应用初始化
下面我们来看下他们分别做了什么
2.1 RuntimeInit.commonInit
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
protected static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
/*
* set handlers; these apply to all threads in the VM. Apps can replace
* the default handler, but not the pre handler.
*/
//设置未捕获异常处理方法
LoggingHandler loggingHandler = new LoggingHandler();
Thread.setUncaughtExceptionPreHandler(loggingHandler);
Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
/*
* Install a TimezoneGetter subclass for ZoneInfo.db
*/
//设置时区
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.
*/
//设置UserAgent
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;
}
2.2 ZygoteInit.nativeZygoteInit
nativeZygoteInit()方法在AndroidRuntime.cpp中,进行了jni映射,对应下面的方法
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
//此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的
gCurRuntime->onZygoteInit();
}
frameworks\base\cmds\app_process\app_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();//1
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();//2
}
- 注释1 :采用单列模式创建ProcessState对象并打开/dev/binder驱动设备,然后调用mmap分配一块内存,并映射内存起始地址。
- 注释2:创建一个新的binder线程,不断进行talkWithDriver
通过ZygoteInit.nativeZygoteInit的初始化,SystemServer可以通过Binder与其他进程进行IPC通信。
2.3 RuntimeInit.applicationInit
frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
applicationInit主要调用了findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);//1
} 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 });//2
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
return new MethodAndArgsCaller(m, argv);//3
}
- 注释1:通过反射得到SystemServer类
- 注释2:通过反射得到SystemServer类的main方法
- 注释3:返回一个MethodAndArgsCaller的Runnable的对象
通过上边一系列的工作,返回一个Runnable对象,然后我们返回到ZygoteInit的main方法
public static void main(String argv[]) {
...
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);//1
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();//2
return;
}
}
...
}
- 注释1:forkSystemServer我们得到了一个包含SystemServer类main方法的MethodAndArgsCaller对象
- 注释2:然后调用MethodAndArgsCaller类的run方法来启动SystemServer。
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });//1
} 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);
}
}
}
- 注释1:通过反射调用SystemServer的main方法
frameworks\base\services\java\com\android\server\SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
到此,SystemServer已经启动起来了,下面我们来看下SystemServer的启动过程
3 SystemServer的启动过程
frameworks\base\services\java\com\android\server\SystemServer.java
private void run() {
try {
...
//将当前线程初始化为looper,将其标记为应用程序的主循环
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Initialize native services.
System.loadLibrary("android_servers");//1
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.
//初始化系统上下文
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();//3
startCoreServices();//4
startOtherServices();//5
} 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");
}
- 注释1:加载libandroid_servers.so
- 注释2:创建SystemServiceManager,对系统服务的声明周期进行管理
- 注释3:启动引导服务(AMS,PowerManagerService,LightsService,PackageManagerService…)
- 注释4:启动核心服务(BatteryService,UsageStatsService,WebViewUpdateService)
- 注释5:启动其他服务(CameraService,InputManagerService,WindowManagerService,NotificationManagerService,AudioService …)
可见,系统将服务分成了3大类,为什么要分批启动呢?笔者认为应该是为了解决各个服务之间的依赖。
3.1 SystemUI和Launcher的启动
SystemServer启动完各种服务之后会调用mActivityManagerService.systemReady
mActivityManagerService.systemReady(new Runnable() {
public void run() {
traceBeginAndSlog("StartSystemUI");
try {
startSystemUi(context, windowManagerF);//启动SystemUI
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
traceEnd();
...
}
});
---
static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
然后回调AMS.systemReady来启动Launcher
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
...
startHomeActivityLocked(currentUserId, "systemReady");//启动Launcher
...
}
到此为止,我们的系统已经启动起来了。
总结
通过分析,我们了解到SystemSerer加载了android_servers.so,创建系统上下文,然后分批启动各种服务,启动完成之后回调AMS.systemReady来启动SystemUI跟Launcher,这样我们的系统就启动完成了。
欢迎关注我的微信公众号