在上一篇文章中我们说到,init进程fork 出了 Zygote 进程,Zygote进程接着会fork 出SystemServer,SystemServer 是Android框架服务进程,负责启动各种java框架服务,现在我们跟一跟它的启动流程,一探究竟。
ZygoteInit.java frameworks\base\core\java\com\android\internal\os
ZygoteServer.java frameworks\base\core\java\com\android\internal\os
public static void main(String argv[]) {
…………
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//调用fork 启动进程
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) { //子进程 即systemServer ,运行runable 后就反回了
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList); // 如果是 zygote ,那么进入无线的loop,等待AMS发送socket通信
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket(); //zygote fork 出的子进程(systemServer走不到这里),关闭socket
}
}
…………
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run(); //调用子进程的main函数,进入子进程
}
}
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
);
/* Containers run without some capabilities, so drop any caps that are not available. */
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);
/* 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,"
+ "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",
};
ZygoteArguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteArguments(args);//解析啥的
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
if (Zygote.nativeSupportsTaggedPointers()) {
/* Enable pointer tagging in the system server. Hardware support for this is present
* in all ARMv8 CPUs. */
parsedArgs.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;
}
/* Request to fork the system server process 正式fork 出子进程*/
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {//如果是systemServer 关闭socket,
if (hasSecondZygote(abiList)) { //判断ABI是否正确
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket(); //关闭 systemServer 的socket
return handleSystemServerProcess(parsedArgs);//进入
}
return null;
}
这是一个JNI方法,进入 com_android_internal_os_Zygote.cpp ,基本上是调用C++方法fork 出子进程,然后把pid反回回去。
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities); //可以看到这里调用的是native方法
// Set the Java Language thread priority to the default value for new apps.
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
ZygoteHooks.postForkCommon();
return pid;
}
接着看 ZygoteInit.java —— forkSystemServer 里的 handleSystemServerProcess,它的返回值是一个runable,意思是做一些预处理,然后找到 SystemServer 的main方法反回回去执行。
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.mNiceName != null) {
Process.setArgV0(parsedArgs.mNiceName);
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);
// Capturing profiles is only supported for debug or eng builds since selinux normally
// prevents it.
if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
try {
Log.d(TAG, "Preparing system server profile");
prepareSystemServerProfile(systemServerClasspath);
} catch (Exception e) {
Log.wtf(TAG, "Failed to set up system server profile", e);
}
}
}
if (parsedArgs.mInvokeWith != null) {
String[] args = parsedArgs.mRemainingArgs;
// 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.
//如果我们有一个非空的系统服务器类路径,我们将不得不复制现有参数并将类路径附加到它。 当我们执行一个新进程时,ART 将正确处理类路径。
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 {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}
/* should never reach here */
}
可以看出,这里是顺序执行 RuntimeInit.commonInit(),ZygoteInit.nativeZygoteInit(),最后返回 RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);
public static final 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();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
RuntimeInit. 没仔细看,应该是做了一些基本的初始化操作。nativeZygoteInit 这个jni 方法找了半天没找到,后来才发现是在 AndroidRuntime.cpp 中注册的,跟踪过去看看源码。
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
gCurRuntime 又是一个 AndroidRuntime 的对象,我们直接进入 AndroidRuntime 里 找到它
进入 app_main.cpp frameworks\base\cmds\app_process ,找到onZygoteInit
virtual void onZygoteInit()
{
sp proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
原来是初始化Binder,然后将线程注册到Binder 线程池。
接着看
RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv, classLoader);
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader); //1
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
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);
}
/*
* 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);
}
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 });
} 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);
}
}
}
实际上就是根据参数找到main 方法,然后一层一层返回回去,最后在 ZygoteInit 的main方法里里面执行,第一阶段完结撒花~
SystemServer 进入main方法
public static void main(String[] args) {
new SystemServer().run();//简单粗暴
}
//构造方法也列没啥东西
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
// Record process start information.
// Note SYSPROP_START_COUNT will increment by *2* on a FDE device when it fully boots;
// one for the password screen, second for the actual boot.
mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
mRuntimeStartUptime = SystemClock.uptimeMillis();
Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime);
// Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
// We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
// TODO: mRuntimeRestart will *not* be set to true if the proccess crashes before
// sys.boot_completed is set. Fix it.
mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
//重点在于run方法,run 方法里主要是进行一些初始化操作,创建Looper什么的,比较值得关注的有几点。
一、createSystemContext 新建系统上下文
二、mSystemServiceManager = new SystemServiceManager(mSystemContext); 根据一 中得到的SystemContext 来初始化 mSystemServiceManager,它负责启动服务,里面有个ArrayList 维护了各个系统服务的实例。
三、启动各种服务
// Start services.
try {
t.traceBegin("StartServices");
startBootstrapServices(t);//开机引导服务 AMS PMS
startCoreServices(t);//核心服务 GpuService BugreportManagerService BatteryService
startOtherServices(t);//其他服务 ALMS WMS 等阿猫阿狗~
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
等上述都干完后,就调用 Looper.loop(); 进入了无限的循环中~
我们看看第一点,新建系统上下文
//新建系统上下文
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
@UnsupportedAppUsage
public static ActivityThread systemMain() {
// The system process on low-memory devices do not get to use hardware
// accelerated drawing, since this can add too much overhead to the
// process.
if (!ActivityManager.isHighEndGfx()) {//判断是不是低内存设备,能否使用硬件加速,这会消耗更多内存
ThreadedRenderer.disable(true);
} else {
ThreadedRenderer.enableForegroundTrimming();
}
ActivityThread thread = new ActivityThread();//创建 ActivityThread,可以理解为主线程
thread.attach(true, 0);
return thread;
}
//构造函数只是创建了一个ResourcesManager实例对象并赋值给自己的成员变量mResourcesManager
@UnsupportedAppUsage
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
然后调用看ActivityThread的成员方法attach()。
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {//参数为 true , 0
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {//进不去
} else {//从这里开始
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();//创建并实例化了一个Instrumentation对象
mInstrumentation.basicInit(this);//只是把 ActivityThread 作为参数传了进去,mInstrumentation 内部增加了一个对外部 ActivityThread 的引用
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);//根据LoadAPK 和 ActivityThread 创造 context,目前内容相同,是两个对象
mInitialApplication = context.mPackageInfo.makeApplication(true, null);//初始化 SystemServer 的 Applicatrion对象
mInitialApplication.onCreate();//调用其onCreate
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
// TODO (b/135719017): Temporary log for debugging IME service.
if (Build.IS_DEBUGGABLE && mHasImeComponent) {
Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
+ "config=" + globalConfig);
}
// We need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
//我们需要立即将此更改应用于资源,因为在返回视图层次结构时将被告知它。
if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
null /* compat */)) {
updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
mResourcesManager.getConfiguration().getLocales());
// This actually changed the resources! Tell everyone about it.
if (mPendingConfiguration == null
|| mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
mPendingConfiguration = globalConfig;
sendMessage(H.CONFIGURATION_CHANGED, globalConfig);//发送消息处理
}
}
}
};
ViewRootImpl.addConfigCallback(configChangedCallback);
}
final void basicInit(ActivityThread thread) {
mThread = thread;
}
接下来是重头戏,创建context
ContextImpl.createAppContext(this, getSystemContext().mPackageInfo) ——> mActivityThread.getSystemContext() ——> ContextImpl.createSystemContext(mActivityThread);
@UnsupportedAppUsage
static ContextImpl createSystemContext(ActivityThread mainThread) {//大意就是,根据ActivityThread 创建 LoadApk,Resource,填充创建好的context然后返回
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
0, null, null);//根据 传进来的 ActivityThread 和 根据 ActivityThread 创建的 PkgInfo , 创建了一个 Context
context.setResources(packageInfo.getResources());//设置context 的 Resourrces 对象,这里是新建的
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
context.mIsSystemOrSystemUiContext = true;
return context;
}
LoadedAPK的这个构造方法只有系统进程创建的时候可以调用。它代表一个系统进程的apk,它里面存储着资源文件的位置,jni包的位置等信息,包名为android。其实代表的就是就是framework-res.apk。该apk仅供systemServer使用。
mSystemContext 的初始化 已经分析完了
然后根据这个 mSystemContext 创建 AppContext
ContextImpl.createAppContext(this, getSystemContext().mPackageInfo)
@UnsupportedAppUsage
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
return createAppContext(mainThread, packageInfo, null);
}
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
String opPackageName) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
0, null, opPackageName);//比上面的只多了一个 opPackageName???关键是 这个 opPackageName 还是个null,日了狗?得出结论,这俩是一毛一样的!
context.setResources(packageInfo.getResources());
context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context);
return context;
}
让我们回到 createSystemContext 方法
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();// (1)
mSystemContext = activityThread.getSystemContext();// 在 1 中已经创建好了 mSystemContext,这里能直接拿到
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
接下来分析 final Context systemUiContext = activityThread.getSystemUiContext();
可以看到几乎一模一样的流程,只是多了一个 displayId,创建完成~撒花
public ContextImpl getSystemUiContext() {
synchronized (this) {
if (mSystemUiContext == null) {
mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
}
return mSystemUiContext;
}
}
static ContextImpl createSystemUiContext(ContextImpl systemContext) {
return createSystemUiContext(systemContext, Display.DEFAULT_DISPLAY);
}
static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
final LoadedApk packageInfo = systemContext.mPackageInfo;
ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
null, null, null, 0, null, null);
context.setResources(createResources(null, packageInfo, null, displayId, null,
packageInfo.getCompatibilityInfo(), null));
context.updateDisplay(displayId);
context.mIsSystemOrSystemUiContext = true;
return context;
}
ActivityThread 和 Context 就构成了Android程序的运行环境。apk的代码最终在ActivityThread线程上运行,通过Context应用程序的大管家,可以调用进程所用到的资源和方法。
SystemServer构建 APK运行环境是为了供 framewrok-res.apk 使用。