最近复习了柯元旦老师的《Android内核剖析》,获益良多。所以想从自己的钻研出发,走一遍柯老师走过的路。我看的《Android内核剖析》版本是基于Android2.3系统来写的,因为我尝试从Android5.1系统再钻研一遍书籍中所钻研过的知识点。
本文将尝试从源码分析SystemServer进程的启动过程,Ams,Wms及其他常用到的服务的创建,以及打开第三方应用的启动过程。
一、SystemServer进程的启动
SystemServer听名字就知道是个非常重要的进程,它是Android Framework启动后fork的第一个进程,可见其重要性。那么该进程在跑什么东西呢?主要是一些系统服务,例如我们常听说的Ams(ActivityManagerService)和Wms(WindowManagerService)。
SystemServer的启动入口在ZygoteInit.java的main函数中。ZygoteInit是Zygote进程加载的第一个类,Zygote进程则是所有Apk应用进程的父进程,所有应用进程都是由Zygote进程fork出来。
从源码开始着手,我们只关心SystemServer相关的部分,ZygoteInit.java:
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = 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 (startSystemServer) {
startSystemServer(abiList, socketName); ②
}
...
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
先看看main函数的参数,它的参数来自启动Zygote的命令,该命令在于系统根目录下的init.rc文件中,其中有一行是:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote -- start-system-server
该行的意思是调用/system/bin/下的app_process命令(或工具),并且后面一串就是其主要参数。
该命令的源码在/frameworks/base/cmds/app_process/app_main.cpp里,我们跟进去看看主要部分:
int main(int argc, char* const argv[])
{
...
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} 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.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
Vector<String8> args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server")); ②
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args); ③
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
看上面标注①的地方:如果有参数是”–start-system-server”,那么变量startSystemServer被置为true,从我们调用的命令来看,这么为true;
标注②:如果startSystemServer为true,那么变量args将添加”start-system-server”这个字符串。我们从变量名args可以猜测到这个变量是保存一些启动参数的。
标注③:毫无疑问这里会启动”com.android.internal.os.ZygoteInit”这个类并且带有参数args,如果一来就会辗转到ZygoteInit的main函数里,并且带有args的参数。
OK,终于明白ZygoteInit的main函数的参数有什么东东,接下来回到该类的main方法里:
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = 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 (startSystemServer) {
startSystemServer(abiList, socketName); ②
}
...
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
标注①:正如刚才分析的,这里的参数是含有”start-system-server”这个字符串,所以此处startSystemServer变量被置为true;
标注②:调用接口startSystemServer();
终于看到启动SystemServer的地方了:
/** * Prepare the arguments and fork for the system server process. */
private static boolean startSystemServer(String abiList, String socketName)
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,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--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) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs); ③
}
return true;
}
标注①:为SystemServer创建一些启动参数,注意这个参数,后面启动会用到。并且从参数可以知道,SystemServer的uid是1000,gid是1000还有一些相关信息都被硬编码的方式编写在此。(一般情况每一个apk应用都有唯一一个uid,用于区分,系统服务如Ams也会根据uid来判断应用的权限,一般uid=1000及其他一些系统的uid程序拥有很多系统权限,uid=0代表root用户)
标注②:重头戏来了!调用Zygote.forkSystemServer()接口fork一个SystemServer进程。fork是linux系统创建子进程的重要方法,其作用是复制当前进程,创建一个新的进程,但是其进程id不相同。当该方法返回值等于0时,代表是创建的新进程。
跟踪进去Zygote.forkSystemServer()接口,发现其调用了JNI的native方法,所以不跟进去,大概流程就是创建了一个新的进程。
标注③:正如上面所说,返回值等于0代表是创建了新的进程,也就是子进程,此时将会调用handleSystemServerProcess()方法去完成SystemServer的创建。
再跟进去该方法:
/** * Finish remaining work for the newly forked system server process. */
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
...
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(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(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}
WrapperInit.execApplication(parsedArgs.invokeWith, ①
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, args);
} else {
...
}
/* should never reach here */
}
标注①:此处会调用WrapperInit.execApplication()方法,不断跟踪进去,会发现其最终调用的代码在于RuntimeInit类中:
RuntimeInit.java:
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.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);
}
/* * 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);
}
该方法的作用是反射调用你要创建的类的main方法。还记得上面创建SystemServer时有创建一堆参数,其最后一个参数是”com.android.server.SystemServer”。没错这个参数辗转最后会作为RuntimeInit.invokeStaticMain()方法的参数,所以这里会反射”com.android.server.SystemServer”该类,并执行其main函数,也就是创建了SystemServer进程后,执行其SystemServer类的main函数。
至此,SystemServer进程的启动过程已大致分析完成。
二、创建Ams、Wms等主要系统服务
这部分源码相对比较简单,主要就是SystemServer中调用的接口。
继续上部分的代码,这里会进入SystemServer的main函数:
/** * The main entry point from zygote. */
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
}
private void run() {
// 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.
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
// property so that it is in sync. We can't do this in
// libnativehelper's JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
// the property. http://b/11463182
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
// Enable the sampling profiler.
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
mProfilerSnapshotTimer = new Timer();
mProfilerSnapshotTimer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// Mmmmmm... more memory!
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);
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
// Within the system server, it is an error to access Environment paths without
// explicitly specifying a user.
Environment.setUserRequired(true);
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper(); ①
// Initialize native services.
System.loadLibrary("android_servers");
nativeInit(); ②
// 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); ④
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Start services.
try {
startBootstrapServices(); ⑤
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
// Loop forever.
Looper.loop(); ⑥
throw new RuntimeException("Main thread loop unexpectedly exited");
}
标注①:准备主线程(也就是正在运行的线程)的Looper;
标注②:native调用,该方法的注释是Called to initialize native system services.
标注③:创建SystemServer的Context,后面继续分析;
标注④:创建SystemServiceManager,其作用就是创建并管理系统服务的生命周期;
标注⑤:
startBootstrapServices();
startCoreServices();
startOtherServices();
连续调用了三个接口,这三个接口正是创建了我们常见的各种系统服务,后面继续分析;
标注⑥:Looper开始循环,等待消息执行。
我们看看SystemServer的Context创建过程:
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
调用了ActivityThread.systemMain():
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()) {
HardwareRenderer.disable(true);
} else {
HardwareRenderer.enableForegroundTrimming();
}
ActivityThread thread = new ActivityThread();
thread.attach(true);
return thread;
}
从这里可以看出SystemServer与普通Apk程序的创建还是很不相同,SystemServer的ActivityThread 是通过ActivityThread 的静态方法systemMain()创建,做了一些简单处理如设置无硬件加速等。不过同样的,其最终还是会调用attach方法,不同的是,普通apk程序调用的是attch(false),那么创建过程肯定也会大不一样。这里就不分析了,继续代码。
mSystemContext = activityThread.getSystemContext()会调用getSystemContext方法,然后里面又会调用ContextImpl.createSystemContext的方法:
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread,
packageInfo, null, null, false, null, null);
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
return context;
}
对比创建Activity的Context,发现会有一些不同:
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
if (activityToken == null) throw new IllegalArgumentException("activityInfo");
return new ContextImpl(null, mainThread,
packageInfo, activityToken, null, false, null, null);
}
其不同性,这里不分析,至此SystemServer的Context已经创建好。
回到SystemServer.main()最重要的部分,创建系统服务,跟踪分析其三连调用
startBootstrapServices();
startCoreServices();
startOtherServices();:
/** * Starts the small tangle of critical services that are needed to get * the system off the ground. These services have complex mutual dependencies * which is why we initialize them all in one place here. Unless your service * is also entwined in these dependencies, it should be initialized in one of * the other functions. */
private void startBootstrapServices() {
// Wait for installd to finish starting up so that it has a chance to
// create critical directories such as /data/user with the appropriate
// permissions. We need this to complete before we initialize other services.
Installer installer = mSystemServiceManager.startService(Installer.class);
// Activity manager runs the show.
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
// Power manager needs to be started early because other services need it.
// Native daemons may be watching for it to be registered so it must be ready
// to handle incoming binder calls immediately (including being able to verify
// the permissions for those calls).
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// Now that the power manager has been started, let the activity manager
// initialize power management features.
mActivityManagerService.initPowerManagement();
// Display manager is needed to provide display metrics before package manager
// starts up.
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
// We need the default display before we can initialize the package manager.
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
// Only run "core" apps if we're encrypting the device.
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
Slog.w(TAG, "Device encrypted - only parsing core apps");
mOnlyCore = true;
}
// Start the package manager.
Slog.i(TAG, "Package Manager");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
Slog.i(TAG, "User Service");
ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
// Initialize attribute cache used to cache resources from packages.
AttributeCache.init(mSystemContext);
// Set up the Application instance for the system process and get started.
mActivityManagerService.setSystemProcess();
}
/** * Starts some essential services that are not tangled up in the bootstrap process. */
private void startCoreServices() {
// Manages LEDs and display backlight.
mSystemServiceManager.startService(LightsService.class);
// Tracks the battery level. Requires LightService.
mSystemServiceManager.startService(BatteryService.class);
// Tracks application usage stats.
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
// Update after UsageStatsService is available, needed before performBootDexOpt.
mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();
// Tracks whether the updatable WebView is in a ready state and watches for update installs.
mSystemServiceManager.startService(WebViewUpdateService.class);
}
/** * Starts a miscellaneous grab bag of stuff that has yet to be refactored * and organized. */
private void startOtherServices() {
final Context context = mSystemContext;
AccountManagerService accountManager = null;
ContentService contentService = null;
VibratorService vibrator = null;
IAlarmManager alarm = null;
MountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
BluetoothManagerService bluetooth = null;
UsbService usb = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
AudioService audioService = null;
MmsServiceBroker mmsService = null;
...
}
其实就是创建并用SystemServiceManager或者ServiceManager管理着这些服务。注意,以前是没有SystemServiceManager,全部服务都是由ServiceManager进行管理的,官方这样修改的意图是什么还需要后续去研究。
上面的代码可以看到我们经常通过Context.getSystemService常用的一些Manager都这里创建了。
至此该部分的研究暂一段落。
三、普通Apk应用程序的启动过程
请看下一篇《源码分析Android 应用进程的启动过程》